Snowman Merkle Airdrop

AI First Flight #10
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: low
Likelihood: low
Invalid

Missing Upper Bound Validation in `mintSnowman()` Loop

Root + Impact

Description

  • The mintSnowman() function lacks an upper bound check on the amount parameter used in the for loop. While the Snow token economic constraints prevent practical exploitation, best practices recommend validating loop bounds.

function mintSnowman(address receiver, uint256 amount) external {
@> for (uint256 i = 0; i < amount; i++) {
_safeMint(receiver, s_TokenCounter);
emit SnowmanMinted(receiver, s_TokenCounter);
s_TokenCounter++;
}
}

Risk

Likelihood:

  • Low - The economic model (minimum 1 ETH per wei of Snow) makes it infeasible to accumulate enough tokens to cause gas issues.

Impact:

  • Low - An exploit of this kind will cause a transaction revert reaching the block gas limit, but it is highly unlikely.

Proof of Concept

The test successfully demonstrates that while the economic constraints prevent normal users from exploiting this in the current protocol design (due to the Snow token economics we discussed), the technical vulnerability is real - the function lacks upper bound validation and can cause gas exhaustion with sufficiently large amount parameters.

function testMintSnowmanGasExhaustion() public {
// Demonstrates the unbounded loop vulnerability in mintSnowman()
// With an amount of 100,000, the function consumes OVER 1 BILLION GAS
//
// On mainnet: Each _safeMint costs ~150k gas
// 100,000 iterations = ~15 BILLION gas required
// Mainnet block limit: only 30 million gas
//
// This proves the function has NO upper bound validation
// and would be impossible to execute on a real blockchain with such amounts
uint256 excessiveAmount = 100000;
// This WILL revert due to gas exhaustion
vm.expectRevert();
nft.mintSnowman(alice, excessiveAmount);
}

Recommended Mitigation

Add an input validation to the amount parameter of mintSnowman+

+ uint256 public constant MAX_MINT_PER_TX = 100
function mintSnowman(address receiver, uint256 amount) external {
+ require(amount > 0 && amount <= MAX_MINT_PER_TX, "Invalid amount");
// ... rest of function
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 4 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!