Snowman Merkle Airdrop

AI First Flight #10
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: low
Likelihood: medium
Invalid

s_hasClaimedSnowman is set but never checked — the same proof + signature can be replayed for repeated claims

Root + Impact

claimSnowman sets s_hasClaimedSnowman but never checks it, and the signature has no nonce or deadline, so one valid proof + signature can be replayed for repeated claims.

Description

claimSnowman sets s_hasClaimedSnowman[receiver] = true but never reads the flag. The EIP-712 signature binds only (receiver, amount) — no nonce and no deadline.

Risk

Likelihood: Medium

Impact: After a successful claim, a user can re-acquire the exact same Snow balance (earn/buy/transfer back) and call claimSnowman again with the identical Merkle proof and signature to mint another batch of Snowman NFTs. This can be repeated to drain the intended 1-claim-per-user design.

Proof of Concept

  1. User U claims successfully with proof + signature for (U, A); s_hasClaimedSnowman[U] becomes true but is never enforced.

  2. U re-acquires exactly A Snow (earn/buy/transfer).

  3. U calls claimSnowman again with the SAME proof and SAME signature.

  4. The call succeeds and mints a second batch of Snowman NFTs; repeatable indefinitely.

Recommended Mitigation

Add require(!s_hasClaimedSnowman[receiver]) at the start of claimSnowman, and include a nonce/deadline in the signed digest as defense in depth.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 1 hour ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!