Snowman::mintSnowman is an unrestricted external function. Any address can call it directly and mint any number of Snowman NFTs without owning Snow, staking Snow, being included in the Merkle tree, or providing a valid signature.
The protocol design says Snowman NFTs are distributed by SnowmanAirdrop after a user stakes Snow:
SnowmanAirdrop::claimSnowman verifies the receiver's Merkle proof and signature.
It transfers the receiver's Snow into the airdrop contract.
It then calls i_snowman.mintSnowman(receiver, amount).
However, the NFT contract does not restrict who can call mintSnowman:
There is no onlyOwner, onlyAirdrop, minter role, or check that msg.sender is the airdrop contract.
This completely breaks the airdrop's core accounting and eligibility guarantees. An attacker can mint arbitrary Snowman NFTs for free, diluting or destroying the value and meaning of the collection. The Merkle proof, signature flow, and Snow staking requirement can all be bypassed.
Add the PoC test in test/AuditFindings.t.sol and run:
PoC:
Restrict mintSnowman so only the airdrop contract can mint. For example:
Alternatively, use an explicit minter role and grant it only to the deployed SnowmanAirdrop.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.