Snowman Merkle Airdrop

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

Improper Access Control on `mintSnowman` allows Unrestricted Minting

# Improper Access Control on `mintSnowma` allows Unrestricted Minting
## Description
* Normally, a `mint` function in an NFT contract should include **access control** to restrict who is allowed to mint tokens. This ensures only trusted contracts or parties can issue new NFTs.
* In the current implementation of the `Snowman` contract, the `mintSnowman` function is marked `external` and has **no access control**, meaning **any external address** can mint unlimited NFTs.
```solidity
function mintSnowman(address receiver, uint256 amount) external {
@> // No access control – anyone can call this
for (uint256 i = 0; i < amount; i++) {
_safeMint(receiver, s_TokenCounter);
s_TokenCounter++;
}
}
```
## Risk
**Likelihood**:
* This will occur whenever a malicious actor directly calls `mintSnowman()` to mint unauthorized NFTs.
**Impact**:
* Anyone can arbitrarily inflate the Snowman NFT supply.
* Completely breaks the trust model and devalues legitimately claimed NFTs.
## Proof of Concept
The following solidity example shows that anyone can call mintSnowman function and claim NFT's.
```solidity
Snowman snowman = Snowman(SNOWMAN_ADDRESS);
// Malicious user calls mint directly
snowman.mintSnowman(msg.sender, 1000); // mints 1000 fake NFTs
```
## Recommended Mitigation
Restrict access to `mintSnowman` so only the `SnowmanAirdrop` contract can call it. Use a one-time setter or constructor injection pattern. Also `i_airdrop` represents address of Snowman Airdrop contract so only via Snowman Airdrop contract Snowman NFT's can be minted.
```diff
+ address private immutable i_airdrop;
- constructor(string memory _SnowmanSvgUri) ERC721("Snowman Airdrop", "SNOWMAN") Ownable(msg.sender) {
+ constructor(string memory _SnowmanSvgUri, address airdrop) ERC721("Snowman Airdrop", "SNOWMAN") Ownable(msg.sender) {
+ require(airdrop != address(0), "Invalid airdrop address");
+ i_airdrop = airdrop;
s_TokenCounter = 0;
s_SnowmanSvgUri = _SnowmanSvgUri;
}
function mintSnowman(address receiver, uint256 amount) external {
+ if (msg.sender != i_airdrop) {
+ revert SM__NotAllowed();
+ }
for (uint256 i = 0; i < amount; i++) {
_safeMint(receiver, s_TokenCounter);
s_TokenCounter++;
}
}
```
This ensures only the trusted `SnowmanAirdrop` contract can call `mintSnowman()` while preventing any external abuse.
Updates

Lead Judging Commences

yeahchibyke Lead Judge 16 days 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.