Snowman Merkle Airdrop

First Flight #42
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Unbounded NFT Minting Can Lead to DoS (Unrestricted Loop + Gas Exhaustion) in `Snowman.sol::mintSnowman()` funtion

The `Snowman.sol::mintSnowman()` function allows any external caller to mint any number of NFTs by specifying an arbitrary amount without upper limits or access control. The function uses a for loop to mint each NFT, which becomes increasingly gas-expensive as amount grows.

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++;
}
}

Impact:

A malicious user can call `mintSnowman()` with a very large amount (e.g., 1_000_000). This will either: Consume excessive gas and revert, causing DoS by exhausting block gas limits. If allowed, bloat the state with excessive NFTs and increase the gas cost of interacting with this contract. This can deny access to other users or crash frontends due to unreasonably large token lists or slow responses.

Proof of Concept:

past the following code in you `TestSnowman.t.sol`

function testDoSByLargeMintingAmount() public {
// Try to mint a very large number of NFTs (e.g., 1 million)
uint256 largeAmount = 1_000_000;
// Expect this to fail due to exceeding block gas limit (DoS vector)
vm.expectRevert(); // Generic revert because of out-of-gas or loop hitting gas cap
nft.mintSnowman(alice, largeAmount);
}

Expected consequences: Transaction fails due to block gas limit. Or succeeds, bloating storage and increasing gas cost of functions like `tokenURI()` and `getTokenCounter()`. Future calls by others could fail due to gas exhaustion or run into degraded performance.

Recommended Mitigation

Add a maximum minting limit per transaction:

function mintSnowman(address receiver, uint256 amount) external {
+ require(amount <= MAX_MINT_PER_TX, "Mint limit exceeded");
for (uint256 i = 0; i < amount; i++) {
_safeMint(receiver, s_TokenCounter);
emit SnowmanMinted(receiver, s_TokenCounter);
s_TokenCounter++;
}
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Unrestricted NFT mint function

The mint function of the Snowman contract is unprotected. Hence, anyone can call it and mint NFTs without necessarily partaking in the airdrop.

Support

FAQs

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