There are 3 functions in FjordAuction.sol contract that have potential overlap in the last second of an auction, which might lead to unintented results.
FjordAuction.sol deals with bidding, unbidding , ending and a bunch of other functionalities. Let's look at 3 functions closely, which are bid(), unbid(), auctionEnd() .With the current implementation, if block.timestamp == auctionEndTime the following operations can all occur:
Bids Can Be Placed:
Bids Can Be Withdrawn (Unbid):
Auction Can Be Ended:
Unclear timing boundry among the functions may lead to inconsistencies in the final total of bids and potential issues for users. Imagine a scenario that bidder1(Alice) , bidder2(bob) and bidder3(Eve) calls bid(), unbid(), auctionEnd() respectively . Now depending on the order of execution of the functions different outcomes will appear. As an example, if the call made to auctionEnd() executed before Alice's call, then this may prevent Alice from accessing auction tokens. If there was a more clear timing check set in auctionEnd(), such as:
then Eve would not able to call the function and Alice could potentially get her tokens based on the bid she made. Contract's state would be affected as well. The state variable multiplier is calculated based on totalBids:
The multiplier is later used in calculating claimable amounts.
In short, It is clear that due to the code implementation and potential last bids, users' claimable amount can be manipulated.
Due to the uncertainty in final bids, Bidders may intentionally/uintentionally face undesired/desired outcomes.
Manual Review, Vs Code
Remove the uncertainty in final bids
The protocol doesn't properly treat the `block.timestamp == auctionEndTime` case. Impact: High - There are at least two possible impacts here: 1. By chance, user bids could land in a block after the `auctionEnd()` is called, not including them in the multiplier calculation, leading to a situation where there are insufficient funds to pay everyone's claim; 2. By malice, where someone can use a script to call `auctionEnd()` + `bid(totalBids)` + `claimTokens()`, effectively depriving all good faith bidders from tokens. Likelihood: Low – The chances of getting a `block.timestamp == auctionEndTime` are pretty slim, but it’s definitely possible.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.