Snowman Merkle Airdrop

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

Missing Access Control on NFT Minting Function

Root + Impact

Description

  • User should only be able to mint NFTs as part of a controlled airdrop process

  • The mintSnowman() function in Snowman.sol has no access control modifiers, allowing any address to mint unlimited NFTs to any recipient address, completely bypassing the airdrop mechanism.

  • The mintSnowman() function should only be callable by authorized addresses (such as the airdrop contract) to maintain the intended distribution mechanism and NFT scarcity.


// Root cause in the codebase with @> marks to highlight the relevant section
// @> Missing access control - anyone can call this function
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:

  • The function is publicly accessible with no restrictions, making exploitation trivial for any user

  • The vulnerability is immediately discoverable through contract interface inspection

Impact:

  • Unlimited minting allows attackers to mint millions of NFTs at minimal gas cost

  • Bypasses all airdrop eligibility requirements and token staking mechanisms

  • Enables griefing attacks by forcing unwanted NFTs onto user addresses

  • Renders the entire airdrop system meaningless and could have economic impact

Proof of Concept

Attacker can mint unlimited NFTs, the below POC shows the attacker minting 100:

// Attacker can mint unlimited NFTs, the below POC shows the attacker minting 100:
function testUnlimitedMinting() public {
address attacker = makeAddr("attacker");
// Attacker mints 100 NFTs to themselves
vm.prank(attacker);
snowman.mintSnowman(attacker, 100);
assertEq(snowman.balanceOf(attacker), 100);
// Attacker now owns 100 NFTs without any eligibility requirements
}

Recommended Mitigation

the fix would be to add a modifier on the function to enforce access control:

- remove this code
+ add this code
// the fix would be to add a modifier on the function to enforce access control:
- function mintSnowman(address receiver, uint256 amount) external {
+ function mintSnowman(address receiver, uint256 amount) external onlyOwner {
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
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.