Snowman Merkle Airdrop

First Flight #42
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: medium
Likelihood: high
Invalid

Missing Total Supply Cap on NFT Minting

Summary

The Snowman contract allows unlimited NFT minting due to the absence of a total supply cap. This can lead to contract state bloat, potential denial-of-service conditions, and operational issues on marketplaces that index the NFT collection.

Description

In the current implementation, the mintSnowman() function accepts any arbitrary amount of NFTs to mint per call and increments the internal counter s_TokenCounter without limit. There is no restriction on the maximum supply of NFTs that can be minted.

Even if proper access controls were added to restrict who can mint, the absence of a hard-coded total supply cap leaves the contract vulnerable to state bloat and potential disruption.

Additionally, attackers or even legitimate users could mint an excessive amount of tokens (intentionally or accidentally), causing the contract storage size and on-chain state to grow unnecessarily. This could lead to increased gas costs, inefficient querying, and operational difficulties for dApps and marketplaces integrating with the collection.

POC

function testMintUnlimitedSnowmanPOC() public {
    vm.startPrank(bob);
    nft.mintSnowman(bob, 2);
    nft.mintSnowman(bob, 2);
    nft.mintSnowman(bob, 2);
    nft.mintSnowman(bob, 2);
    vm.stopPrank();

    assert(nft.getTokenCounter() == 8);
}

Impact

Excessive state growth can increase gas costs for functions that iterate over tokens.
Marketplace indexing (OpenSea, Blur, etc.) may fail or become inefficient due to extreme collection sizes.
In extreme edge cases, token ID overflows may occur (especially if storage slots are manipulated externally).

Severity

MEDIUM

Likelihood

HIGH

Recommended mitigation

Implement a maximum supply constraint in the minting function to prevent unbounded growth. Example:

uint256 public constant MAX_SUPPLY = 10000;
function mintSnowman(address receiver, uint256 amount) external {
require(s_TokenCounter + amount <= MAX_SUPPLY, "Max supply reached");
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 5 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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