Skip to content

Latest commit

 

History

History
80 lines (56 loc) · 3.73 KB

048.md

File metadata and controls

80 lines (56 loc) · 3.73 KB

Furry Infrared Mockingbird

Medium

Highest Bidder has the power to outbid new bidders with lesser bid by frontrunning in both NounsAuctionHouseV3 and NounsAuctionHouseV2

Summary

The missing constraint in createBid() allows highest bidder to bid again. If a new bidder tries to bid then it can be frontrun by bidding the (new bid - ( new bid * minBidIncrementPercentage)) < amount < new bid. Which is essentially lesser than the new bid. But enough for the transaction of a new Bidder the revert. By this the Highest bidder is able to retain its position by paying less instead of having to outbid the new bidder again.

Root Cause

In Both https://github.com/sherlock-audit/2024-11-nounsdao/blob/main/nouns-monorepo/packages/nouns-contracts/contracts/NounsAuctionHouseV3.sol#L157C7-L160C11 and https://github.com/sherlock-audit/2024-11-nounsdao/blob/main/nouns-monorepo/packages/nouns-contracts/contracts/NounsAuctionHouseV2.sol#L141C1-L144C11 there is a missing check of new higher bidder to not be equal to the auctionStorage.bidder. Which gives highest bidder an extra edge to retain its position.

Internal pre-conditions

  1. The Chain should support frontrunning.

External pre-conditions

No response

Attack Path

  1. Alice bids 1 Ether in Auction
  2. Bob wants to bid 2 Ether. Bob sends txn to the mempool.
  3. Alice reads to mempool. Now, Alice can either let Bob's txn to go through. Which means Alice will later require to bid amount ( 2 + 2* 0.02). Which is > 2.04 Ether. Considering minBidIncrementPercentage = 2%.
  4. Or Alice can frontrun Bob's txn and bid 1.97 Ether. Which lead to next min Bid to be 2.0094.
  5. Now, Bob bid is 2 < 2.0094. Leads to Bob bid to revert.
  6. Essentially Alice just outbid bob with just 1.97 Ether instead of 2.041. The difference increases drastically as the amounts gets bigger.

Impact

The highest bidder has the unwanted advantage to retain its position by essentially paying less. Which is not intended by design of the protocol.

PoC

Add the following test in https://github.com/sherlock-audit/2024-11-nounsdao/blob/main/nouns-monorepo/packages/nouns-contracts/test/foundry/NounsAuctionHouseV3.t.sol

    function test_createBid_getsFrontrunAndHighestBidderPayingLessThanAnticipated() public {
        uint256 nounId = auction.auction().nounId;
        address bidder1 = address(0x4444);
        address bidder2 = address(0x5555);

        console.log("Bidder1 Bid 1.1 Ether");
        vm.deal(bidder1, 1.1 ether);
        vm.prank(bidder1);
        auction.createBid{ value: 1.1 ether }(nounId);

        console.log("Bidder2 is going to Bid 2.2 Ether");
        console.log("Bidder1 Bids 2.16 Ether which will cause Bidder2 txn to revert as 2.2 is < 2% increment in 2.16");
        vm.deal(bidder1, 2.16 ether);
        vm.prank(bidder1);
        auction.createBid{ value: 2.16 ether }(nounId);

        assertEq(bidder1.balance, 1.1 ether);

        console.log("Bidder2 txn reverts as 2.2 Ether doesn't satisfy minBidIncrementPercentage constraint");
        vm.deal(bidder2, 2.2 ether);
        vm.prank(bidder2);
        vm.expectRevert('Must send more than last bid by minBidIncrementPercentage amount');
        auction.createBid{ value: 2.2 ether }(nounId);

        assertEq(bidder1.balance, 1.1 ether);
        assertEq(bidder2.balance, 2.2 ether);
    }

Output

  Bidder1 Bid 1.1 Ether
  Bidder2 is going to Bid 2.2 Ether
  Bidder1 Bids 2.16 Ether which will cause Bidder2 txn to revert as 2.2 is < 2% increment in 2.16
  Bidder2 txn reverts as 2.2 Ether doesn't satisfy minBidIncrementPercentage constraint

Mitigation

By adding require(_auction.bidder != msg.sender, 'Highest bidder cannot outbid itself'); check we can present the same user to frontrun other bids.