After the end of the auction there is still an opportunity for a user to make a bid and get a bigger reward or even the whole reawrd of the auction if he match the totalBids
.
In the FjordAuction::bid
and unbid
functions it's checked if block.timestamp > auctionEndTime
and only if this is true, the function reverts with error AuctionAlreadyEnded
. This means that if block.temstamp = auctionEndTime
the function wont revert and the user will be able to bid. In the same time the FjordAuction::auctionEnd
function the condition to revert the function is block.temstamp < auctionEndTime
which also means that the function wont revert if block.temstamp = auctionEndTime
. This allows a user to call both functions in the same block, first ending the auction and then biding. For example:* *
There is an auction with a price of 1 weth.
Ann bids 100 points.
Bob submits a transaction in a block where block.timestamp = auctionEndTime
where he is calling three functions in the order below:
auctionEnd -> multiplier = 1e18(weth) * 1e18(precision) / 100(totalBids) = 1e34;
bid -> Bob bids 100 points;
claimTokens -> using the formula: claimable = userBids.mul(multiplier).div(PRECISION_18
where claimable = 100 * 1e34 / 1e18 = 1e18
which means Bob will be able to get the whole reward;
Some users can get the whole reward or a bigger part than they deserve, just by bidding after the end of the auction.
Manual Review
Make and additional check:
OR
Change the checks in the bid and unbid functions to:
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.