Little Azure Dove
High
The settleCurrentAndCreateNewAuction
function in NounsAuctionHouseV2 is vulnerable to a Denial-of-Service attack through gas manipulation, potentially forcing the contract into a paused state and disrupting the auction system.
https://github.com/sherlock-audit/2024-11-nounsdao/blob/main/nouns-monorepo/packages/nouns-contracts/contracts/NounsAuctionHouseV2.sol#L102
https://github.com/sherlock-audit/2024-11-nounsdao/blob/main/nouns-monorepo/packages/nouns-contracts/contracts/NounsAuctionHouseV2.sol#L247
The vulnerability stems from insufficient gas handling in the _createAuction
function, where any error during the minting process triggers a contract pause without distinguishing between out-of-gas errors and legitimate failures.
- Contract must be in an unpaused state
- Current auction must be ready for settlement
- Attacker needs enough ETH to pay for transaction gas
- Timing requirement: Must be executed when current auction is ready for settlement
- Wait for an auction to reach settlement time
- Calculate minimum gas needed to reach
nouns.mint()
- Call
settleCurrentAndCreateNewAuction
with precisely limited gas:
function executeAttack() external {
uint256 gasLimit = calculateMinGas(); // Just enough to reach mint()
(bool success,) = address(auctionHouse).call{gas: gasLimit}(
abi.encodeWithSignature("settleCurrentAndCreateNewAuction()")
);
}
- Gas exhaustion during mint causes catch block execution
- Contract enters paused state
-
Protocol Operation Disruption:
- Auctions can be repeatedly forced into pause state
- Requires DAO governance action to unpause
- Disrupts daily auction schedule
-
Economic Impact:
- Lost revenue during paused periods
- Reduced protocol activity
- Potential loss of user confidence
-
Governance Implications:
- Frequent governance interventions required
- Time delays in resuming operations
- Resource drain on DAO
- Add gas requirement check:
function _createAuction() internal {
uint256 requiredGas = 750_000; // Safe gas estimate
require(gasleft() >= requiredGas, "Insufficient gas");
try nouns.mint() returns (uint256 nounId) {
// ... existing auction creation code ...
} catch Error(string memory reason) {
if (!isOutOfGasError(reason)) {
_pause();
}
revert(reason);
}
}
- Alternative approach:
- Separate settlement and creation into two transactions
- Implement gas-efficient minting process
- Add specific error handling for OOG conditions