DeFiFoundry
20,000 USDC
View results
Submission Details
Severity: medium
Valid

Timestamp checks at the FjordAuction contract allows malicious parties to make auctions insolvent

Summary

The timestamp sanity checks at the FjordAuction contract allow a malicious user to bid after an auction has ended. This leads to an inflated claim eligibility for the user and to auction insolvency.

Vulnerability Details

The auctionEnd function requires the block timestamp must be at least equal to the auction's end time. Then it sets the multiplier variable based on the total amount of bids.

function auctionEnd() external {
if (block.timestamp < auctionEndTime) {
revert AuctionNotYetEnded();
}
...
multiplier = totalTokens.mul(PRECISION_18).div(totalBids);
...
}

The bid function requires the block timestamp is at most equal to the auction's end time, but doesn't check if the auction is already over by verifying the boolean value of the ended variable:

function bid(uint256 amount) external {
if (block.timestamp > auctionEndTime) {
revert AuctionAlreadyEnded();
}
...
}

If a malicious party calls both auctionEnd and bid sequentially via a single transaction in the moment when block.timestamp equals auctionEndTime, then this user will be able to place a bid after the auction is over and the multiplier is computated.

Since this multiplier was calculated taking into account an X amount of bids that did not account this malicious party's bids, the claiming logic becomes insolvent:
Let us have an auction with 1k Fjord points worth of bids and a total tokens worth 10k USDC.
Alice calls the auction end and bids 1k Fjord points.
The multiplier would be 10k USDC * PRECISION_18 / 1k Fjord points.

Alice then claims the tokens and the other bidders end up left empty handed.

Impact

Malicious parties could use this vulnerability to make auctions insolvent.
This specific order of operations allows legitimate bidders to have a diluted token claims.

Tools Used

Manual review

Recommended Mitigation

Make sure to check the ended boolean variable in order to allow bids, unbids and claims. If the ended value is false, only bids and unbids should be open. If the ended value is true, only claims should be open.

Updates

Lead Judging Commences

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Users can bid in the same block when the actionEnd could be called (`block.timestamp==actionEndTime`), depending on the order of txs in block they could lose funds

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.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.