Snowman Merkle Airdrop

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

Unrestricted mint amount

Unrestricted mint amount

Description

  • DesThe mintSnowman function is intended to mint a specified number of Snowman NFTs to a given receiver. Under normal usage, a user can mint a small number of NFTs in a single transaction, updating ownership and token counters without exceeding gas limits.

  • The function allows the caller to specify an arbitrarily large amount. Because each NFT is minted inside a for loop using _safeMint, very large values cause the transaction to consume excessive gas, potentially exceeding the block gas limit. This results in the transaction failing and effectively creates a Denial-of-Service (DoS) condition, preventing the minting of Snowman NFTs in a single call and disrupting expected contract functionality.

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:

  • This will occur when a user attempts to mint a very large number of Snowman NFTs in a single transaction, causing the for-loop to exceed the block gas limit.

  • This will occur because the contract places no upper bound on the amount parameter, allowing any caller to submit arbitrarily large values.

Impact:

  • Large mint transactions fail due to gas exhaustion, preventing users from minting Snowman NFTs in a single call.

  • Automated scripts or batch airdrops that rely on bulk minting may fail, causing delays or interruption in planned distributions.

  • Users submitting large transactions may lose gas fees for failed transactions, resulting in wasted funds.

  • Repeated failed transactions and disrupted airdrops could harm user trust in the protocol.

Proof of Concept

Add this piece of code in your TestSnowman.t.sol file. and then run `forge test --mt test_mintUnlimitedAmount -vvv`

function test_mintUnlimitedAmount() public {
uint256 largeAmount = 500; // smaller, triggers high gas
vm.prank(attacker);
uint256 startGas = gasleft();
nft.mintSnowman(attacker, largeAmount);
uint256 endGas = gasleft();
uint256 gasUsed = startGas - endGas;
console2.log("Gas used for large mint:", gasUsed);
assert(gasUsed > 10_000_000); // just a high gas indicator
}

Recommended Mitigation

Set a limit on the number of NFT that can be minted

+ uint256 constant MAX_MINT_PER_TX = 20;
+ function mintSnowman(address receiver, uint256 amount) external {
+ require(amount > 0 && amount <= MAX_MINT_PER_TX, "Too many Snowmen at once");
+ for (uint256 i = 0; i < amount; i++) {
+ _safeMint(receiver, s_TokenCounter);
+ emit SnowmanMinted(receiver, s_TokenCounter);
+ s_TokenCounter++;
+ }
+ }
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 16 days 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!