The FjordAuction
contract represents an auction, which the admin can create. Users can bid FjordPoints
tokens to the auction, using the function bid
, so that later when the auction ends, using the auctionEnd
function, the user can claim their proportionally calculated tokens of the protocol token, using the function claimTokens
. Let's have a deeper look at the bid
and auctionEnd
functions:
As we can see, the bid
function checks whether the current timestamp is bigger than the auctionEndTime
, which should prevent people from bidding when the time of the auction has passed. The auctionEnd
function checks if the current timestamp is less than the auctionEndTime
. This way people cannot end an auction if the time has not passed. However, the problem lies in the fact that both functions do not check if the current timestamp is equal to auctionEndTime
. With that in mind, we can imagine the following scenario:
A malicious user decides to call bid
and auctionEnd
functions when the block.timestamp
is equal to auctionEndTime
.
First, the user calls the auctionEnd
function, the auction ends and the multiplier
is calculated.
Immediately after, they call the bid
function with a big amount
. In that way, the user increases the totalBids
, without recalculating the multiplier
, which is inversely proportional to the totalBids
. Since the user has made another bid, his own userBids
also increased.
When the user calls the claimTokens
function, the multiplier
does not reflect the increase in totalBids
from the previous action. SinceuserBids
was increased without the multiplier
being recalculated, the user will claim a larger proportion of the auction prize than he is entitled to.
Although userBids
are set to 0
after claimTokens
, the user can bid
again during the same timestamp, incrementing userBids
, allowing him to further drain funds from the auction prize pool.
Since the user can claim a larger proportion of the prize pool, some users would be unable to claim their prizes since there would not be enough tokens in the contract. Further, the malicious user could potentially even claim the whole prize pool.
A malicious user can cheat the contract, allowing him to claim a larger proportion of the prize pool than he is entitled to. This also impacts other users as some/all would not be able to claim their rewards.
Manual Review
Consider modifying the first if-statement in auctionEnd
function:
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.