Snowman Merkle Airdrop

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

Snow.earnSnow uses a single global s_earnTimer, so only one user can earn per week

Description

Three low-severity issues in SnowmanAirdrop.sol:

  1. No nonce or deadline on the signed message. The signed struct is only SnowmanClaim(receiver, amount). With no nonce and no expiry, a signature is not single-use and never goes stale, which is the underlying reason a claim can be replayed.

  2. Unused storage array. address[] private s_claimers; is declared but never written to or read anywhere in the contract. It is dead code.

  3. Floating pragma. pragma solidity ^0.8.24; lets the contract compile under a range of compiler versions instead of the one it was written and tested against.

Risk

Impact: Low. On their own these do not cause direct loss; item (1) is a contributing factor to replay, while (2) and (3) are code-quality / footgun issues.

Likelihood: Low.

Proof of Concept

The signed struct carries no nonce/deadline, so the same signature stays valid indefinitely:

// getMessageHash only binds (receiver, amount) — nothing that makes a signature single-use or expiring:
return _hashTypedDataV4(
keccak256(abi.encode(MESSAGE_TYPEHASH, SnowmanClaim({receiver: receiver, amount: amount})))
);

Because the digest binds only receiver and amount, there is no nonce to consume on use and no deadline to expire, so a signature captured once remains valid forever and can be resubmitted later.

Recommended Mitigation

  • Add a nonce (per receiver, incremented on each successful claim) and a deadline to the SnowmanClaim struct and the MESSAGE_TYPEHASH, verify the deadline hasn't passed, and consume the nonce on claim.

  • Delete the unused s_claimers array.

  • Pin the pragma to a single version: pragma solidity 0.8.24;.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 2 hours 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!