Snowman Merkle Airdrop

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

No Upper Cap on Total Supply in `Snowman.sol::mintSnowman()` function

[High] No Upper Cap on Total Supply in Snowman.sol::mintSnowman() function


Description

The mintSnowman() function in Snowman.sol lacks any mechanism to cap the total number of tokens that can be minted. The s_TokenCounter simply increments indefinitely with each mint operation. This design flaw, especially in the absence of robust access control (as noted in H-3), creates significant risks for unintentional or malicious over-minting.


Risk

An attacker, or even a legitimate owner if not careful, can mint an excessive number of NFTs, leading to several critical issues:

  1. Unbounded Token Growth: This directly leads to increased storage costs and potentially higher gas fees for functions that interact with the token supply or iterate through token IDs (e.g., ownerOf, tokenByIndex).

  2. Indexer/Marketplace Instability: Off-chain indexers, analytics platforms, and NFT marketplaces may struggle, crash, or refuse to list collections with an effectively unbounded or excessively large supply, due to resource constraints.

  3. Unexpected Application Behavior: DApps or integrations built on top of the NFT collection might exhibit unexpected behavior, or even fail, if they assume a fixed or reasonably capped total supply.

  4. Token Devaluation: An unlimited supply fundamentally undermines the scarcity and thus the market value of each individual NFT in the collection.


Proof of Concept

The snippet below from mintSnowman shows the _safeMint call within a loop, with s_TokenCounter incrementing without any upper bound check:

function mintSnowman(address receiver, uint256 amount) external {
for (uint256 i = 0; i < amount; i++) {
@> _safeMint(receiver, s_TokenCounter); // No check on s_TokenCounter against a max supply
emit SnowmanMinted(receiver, s_TokenCounter);
s_TokenCounter++;
}
}

The "Proof of Code" provided clearly illustrates the ability to attempt to mint an arbitrarily large number of tokens (e.g., 1_000_0000).


Recommended Mitigation

Introduce a MAX_SUPPLY constant to define the maximum allowable number of tokens in the collection. Implement a modifier or a require statement within the mintSnowman function to ensure that the current token supply plus the amount being minted does not exceed this MAX_SUPPLY.

+ uint256 public constant MAX_SUPPLY = 10000; // Define your desired maximum supply
+
+ modifier supplyCheck(uint256 amount) {
+ require(s_TokenCounter + amount <= MAX_SUPPLY, "Snowman: Exceeds max supply");
+ _;
+ }
+
- function mintSnowman(address receiver, uint256 amount) external {
+ function mintSnowman(address receiver, uint256 amount) external onlyOwner supplyCheck(amount) { // Combined with H-3 access control mitigation
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
Invalidated
Reason: Design choice

Support

FAQs

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