Platform: Code4rena
Start Date: 02/06/2023
Pot Size: $100,000 USDC
Total HM: 15
Participants: 75
Period: 7 days
Judge: Picodes
Total Solo HM: 5
Id: 249
League: ETH
Rank: 75/75
Findings: 1
Award: $0.00
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xWaitress
Also found by: Josiah, LaScaloneta, RaymondFam, T1MOH, peanuts
0 USDC - $0.00
https://github.com/code-423n4/2023-06-stader/blob/main/contracts/Auction.sol#L62-L78
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.
Consider this hypothetical situation:
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()
.
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.
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.
Should Bob's bid succeed, per addBid()
logic on line 71:
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); }
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.
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.
DoS
#0 - c4-judge
2023-06-10T14:41:37Z
Picodes marked the issue as primary issue
#1 - c4-judge
2023-06-10T14:41:47Z
Picodes marked the issue as duplicate of #70
#2 - c4-judge
2023-07-02T11:04:14Z
Picodes marked the issue as satisfactory
#3 - c4-judge
2023-07-13T10:09:55Z
Picodes marked the issue as unsatisfactory: Invalid
#4 - Picodes
2023-07-13T10:10:57Z
Giving unsatisfactory to this submission as it is with sufficient likelihood a direct copy of #110