Snowman Merkle Airdrop

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

Missing Single-Claim Restriction Enforcement in SnowmanAirdrop.sol

Root + Impact

Description

  • Normal Behavior: The claimSnowman function should allow each user to claim NFTs only once, enforced by s_hasClaimedSnowman.

  • Specific Issue: The function sets s_hasClaimedSnowman[receiver] = true but doesn’t check it before processing, allowing multiple claims if users acquire more Snow tokens and new proofs/signatures.

// Root cause in the codebase with @> marks to highlight the relevant section
function claimSnowman(address receiver, bytes32[] calldata merkleProof, uint8 v, bytes32 r, bytes32 s)
external
nonReentrant
{
// @> No check for s_hasClaimedSnowman[receiver]
s_hasClaimedSnowman[receiver] = true;// @> Set but not enforced
i_snowman.mintSnowman(receiver, amount);
}

Risk

Likelihood:

  • Occurs when users acquire additional Snow tokens and generate new valid proofs/signatures.

  • Feasible during the 12-week farming period when Snow tokens are obtainable.

Impact:

  • Multiple unauthorized claims inflate NFT supply, reducing scarcity.

  • Undermines airdrop fairness, favoring users who manipulate balances.

Proof of Concept

SnowmanAirdrop airdrop = SnowmanAirdrop(airdropAddress);
airdrop.claimSnowman(user, merkleProof1, v1, r1, s1);// First claim// User acquires more SNOW, gets new proof/signature
airdrop.claimSnowman(user, merkleProof2, v2, r2, s2);// Second claim

Recommended Mitigation

+ if (s_hasClaimedSnowman[receiver]) revert("Already claimed");
s_hasClaimedSnowman[receiver] = true;
Updates

Lead Judging Commences

yeahchibyke Lead Judge 5 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Lack of claim check

The claim function of the Snowman Airdrop contract doesn't check that a recipient has already claimed a Snowman. This poses no significant risk as is as farming period must have been long concluded before snapshot, creation of merkle script, and finally claiming.

Support

FAQs

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