code-423n4 / 2023-06-stader-findings

1 stars 1 forks source link

FRONT-RUNNING SUSCEPTIBILITY IN ADDBID() #414

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-06-stader/blob/main/contracts/Auction.sol#L62-L78

Vulnerability details

Impact

Auction.addBid is susceptible to front-running attacks. This vulnerability presents a significant risk as participants with adequate knowledge or skill could manipulate Ethereum transaction ordering to gain undue advantage, potentially compromising the fairness and integrity of the auction process. This risk is particularly pronounced during the auction's final stages when bidding activity typically spikes, and such manipulations could considerably influence the auction's outcome.

Additionally, the exploitation potential goes beyond simply winning the auction; it also includes winning at the lowest possible cost. Exploiters could tweak their bids to barely surpass other participants, avoiding unnecessary expense.

Proof of Concept

Consider this hypothetical situation:

  1. Both Alice and Bob intend to participate in a Stader token auction. As the auction approaches its close, Alice places a 5 ETH bid using addBid().

  2. Conversely, Bob holds out until the very last moment, monitoring the Ethereum mempool and noting Alice's pending transaction. He opts to bid precisely 5 ETH, but sets a higher gas fee with the intent of having his transaction processed ahead of Alice's.

  3. Given Ethereum miners typically prioritize transactions with higher gas fees, it's probable that Bob's transaction gets included in the blockchain before Alice's, even though Alice initiated her transaction earlier.

  4. Should Bob's bid succeed, per addBid() logic on line 71:

Auction.sol#L62-L78

    function addBid(uint256 lotId) external payable override whenNotPaused {
        // reject payments of 0 ETH
        if (msg.value == 0) revert InSufficientETH();

        LotItem storage lotItem = lots[lotId];
        if (block.number > lotItem.endBlock) revert AuctionEnded();

        uint256 totalUserBid = lotItem.bids[msg.sender] + msg.value;

71:        if (totalUserBid < lotItem.highestBidAmount + bidIncrement) revert InSufficientBid();

        lotItem.highestBidder = msg.sender;
        lotItem.highestBidAmount = totalUserBid;
        lotItem.bids[msg.sender] = totalUserBid;

        emit BidPlaced(lotId, msg.sender, totalUserBid);
    }
  1. Alice would need to raise her bid by an additional bidIncrement to remain competitive. Since Alice's transaction was still pending when Bob's was mined, her transaction gets reversed due to 'InSufficientBid()', even though she bid the same ETH amount as Bob.

Again, this isn't solely about winning; it's about winning at the lowest viable cost. An exploiter, like Bob, doesn't need to outbid; they simply need to strategically bid, ensuring their transaction gets processed first, which enables them to pay the minimum price. Bob could always repeat this process to outmaneuver another bidder, but only needing to increment totalUserBid until the auction concludes.

Recommended Mitigation Steps

It is suggested extending the auction duration whenever a new highest bid is placed, possibly in the last 10 blocks. This could provide others with an opportunity to respond, thereby facilitating a more equitable auction.

Assessed type

DoS

c4-judge commented 1 year ago

Picodes marked the issue as primary issue

c4-judge commented 1 year ago

Picodes marked the issue as duplicate of #70

c4-judge commented 1 year ago

Picodes marked the issue as satisfactory

c4-judge commented 1 year ago

Picodes marked the issue as unsatisfactory: Invalid

Picodes commented 1 year ago

Giving unsatisfactory to this submission as it is with sufficient likelihood a direct copy of #110