Snowman Merkle Airdrop

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

`SnowmanAirdrop::s_claimers` array is declared but never populated

Root + Impact

Description

  • The SnowmanAirdrop contract declares an address[] private s_claimers array intended to store addresses of users who claim Snowman NFTs.

  • This array is never written to anywhere in the contract. No address is ever pushed to it.

  • This is dead code that wastes a storage slot and indicates missing functionality.

// src/SnowmanAirdrop.sol
address[] private s_claimers; // @> declared but never populated anywhere in the contract

Risk

Likelihood:

  • This is a code quality issue present in the deployed contract.

Impact:

  • Any off-chain system or future contract relying on s_claimers to track who has claimed will get empty data.

  • Wasted storage slot deployment cost.


Proof of Concept

A simple code review of the entire SnowmanAirdrop contract reveals that s_claimers appears exactly once — in its declaration at line 42. There is no .push() call, no loop iterating over it, no getter function returning it, and no reference to it in any other function. The claimSnowman function (the only function that modifies state) updates s_hasClaimedSnowman and emits an event, but never touches s_claimers.

Verification:

  1. Search for s_claimers across the entire contract — only found at line 42 (declaration).

  2. The claimSnowman function at line 69-99 does not contain any s_claimers.push(receiver) call.

  3. No getter function exists to return the s_claimers array.

  4. The storage slot for this dynamic array is allocated but will always remain empty (length 0).

// The only occurrence of s_claimers in the entire contract:
address[] private s_claimers; // line 42 — declared but never written to or read from

Recommended Mitigation

Either remove the unused s_claimers array entirely to save deployment gas and reduce contract complexity, or populate it in claimSnowman so it fulfills its intended purpose of tracking claimer addresses. If the array is meant to provide an on-chain record of all claimers (e.g., for off-chain indexing or future contract interactions), it should be populated alongside the existing s_hasClaimedSnowman mapping update. A getter function should also be added to make the data accessible.

function claimSnowman(...) external nonReentrant {
...
s_hasClaimedSnowman[receiver] = true;
+ s_claimers.push(receiver);
emit SnowmanClaimedSuccessfully(receiver, amount);
i_snowman.mintSnowman(receiver, amount);
}
+ function getClaimers() external view returns (address[] memory) {
+ return s_claimers;
+ }
Updates

Lead Judging Commences

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