Starknet Auction

First Flight #26
Beginner FriendlyNFT
100 EXP
View results
Submission Details
Severity: medium
Invalid

Race condition during bidding

Summary

The contract relies on block timestamps to determine whether an auction is still open, which can introduce race conditions. If bids are placed near the auction's end time, multiple users might think they have won, leading to inconsistencies in bid processing.

Vulnerability Details

The auction’s validity is determined by comparing the current block’s timestamp with the auction's end time. Because multiple transactions can occur in the same block, two users could both submit bids within the same block just before the auction ends, creating a race condition where the final bid is unclear.

Two or more users place bids near the end of the auction, believing they will win.

Due to the lack of fine-grained time control, multiple bids are accepted within the same block, but only one can be valid, creating confusion and possible disputes.

Impact

This leads to inconsistent auction results, where users may believe they have successfully placed the highest bid when, in fact, they have not. This reduces trust in the auction system and could lead to disputes among participants.

Tools Used

Manual review

Recommendations

Use block numbers instead of timestamps to manage auction end conditions, or implement a buffer period that disables bidding within the last few blocks to ensure only one bid can be processed at the close of the auction.

fn bid(ref self: ContractState, amount: u64) {
let current_block_number = get_block_number(); // Use block number instead of timestamp
let erc20_dispatcher = IERC20Dispatcher { contract_address: self.erc20_token.read() };
let sender = get_caller_address();
let receiver = get_contract_address();
let current_bid = self.highest_bid.read();
assert(self.started.read(), 'Auction is not started');
assert(current_block_number < self.bidding_end.read() + 1, 'Auction ended'); // Buffer of 1 block
assert(amount > current_bid, 'The bid is not sufficient');
self.bid_values.entry(sender).write(amount);
self.emit(NewHighestBid {amount: self.highest_bid.read(), sender: sender});
self.highest_bidder.write(sender);
self.highest_bid.write(amount);
erc20_dispatcher.transfer(receiver, amount.into());
}
Updates

Lead Judging Commences

bube Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.