A malicious user can call the FjordAuction::bid function after the FjordAuction::auctionEnd function has been executed. This issue arises because both the FjordAuction::bid and FjordAuction::auctionEnd functions check block.timestamp against FjordAuction::auctionEndTime but do not account for the scenario where block.timestamp equals FjordAuction::auctionEndTime. Details are provided in the 'Proof of Concept' section.
A malicious user can bid after the auction has ended to receive more tokens than expected. As a result, some bidders are unable to claim auction tokens and lose their FjordPoints tokens.
First, the malicious user creates an attacker contract to call the FjordAuction::auctionEnd function and the FjordAuction::bid function within a single transaction. Then, they wait until the block.timestamp equals FjordAuction::auctionEndTime to send the transaction and execute the attack.
Add the code for the Attacker contract to the test/unit/auction.t.sol file:
Add the test case and run the command forge test --mt testBidAfterAuctionEnd:
Update function FjordAuction::auctionEnd:
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.