An attacker can steal the auctionTokens
from other eligible bidders of an auction by making a bid after the auction has ended.
The FjordAuction
contract is used to allow the Fjord community members to redeem thier FjordPoints
for auctionTokens
via a bidding process. The FjordAuction.bid
function is used to make a bid and the FjordAuction.auctionEnd
function is used to end the auction once the auction has expired and the FjordAuction.claimTokens
is used to claim the auctionTokens
corresponding to the respective bid amount of the bidder (msg.sender).
But the issue here is that the contract allows to end the auction and make a bid simultaneously at block.timestamp == auctionEndTime
as shown in the following code snippets:
This vulnerability allows an Attacker to call FjordAuction.auctionEnd
(In which the multiplier is calculated
) and end the auction
and then in the same transaction to call the FjordAuction.bid
and increase attacker's bid amount
. Then in the same transaction the attacker can call FjordAuction.claimTokens
and claim the auctionTokens
corresponding to the attacker's inflated bid amount
. Since the multiplier does not account
for the bid amount made after the auction end
, this will allow the attacker to steal funds
(auction tokens) from the other bidders. Other bidders will not be able to claim thier eligible auctionTokens
since the contract does not have enough balance as the attacker has stolen the funds from the contract.
Please add the following testcase to the test/unit/auction.t.sol
file and execute the following command.
forge test --match-test testClaimTokensAttackBid
https://github.com/Cyfrin/2024-08-fjord/blob/main/src/FjordAuction.sol#L181-L184
https://github.com/Cyfrin/2024-08-fjord/blob/main/src/FjordAuction.sol#L143-L146
https://github.com/Cyfrin/2024-08-fjord/blob/main/src/FjordAuction.sol#L197
https://github.com/Cyfrin/2024-08-fjord/blob/main/src/FjordAuction.sol#L207-L222
Manual Review, Foundry and VSCode
Hence it is recommended to change the auctionEndTime
timestamp conditional check in the FjordAuction.auctionEnd()
function to block.timestamp <= auctionEndTime
as shown below:
The above change will ensure that auctions can not be ended when the block.timestamp == auctionEndTime
which means an attacker can not make a bid
after the auction has ended
, since there is no overlap of the timestamps during which the bid
and auctionEnd
transaction can be called.
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.