Snowman Merkle Airdrop

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

[L-1] Global `s_earnTimer` in `Snow::earnSnow` and `Snow::buySnow` blocks all users from earning when any single user earns

Global timer variable in earnSnow locks out all users for one week per call

Description

The Snow::earnSnow function is intended to allow each user to mint 1 free Snow token once per week. The cooldown is tracked by s_earnTimer, a single global uint256.

When any user calls earnSnow, s_earnTimer is set to block.timestamp, which blocks all other users from calling earnSnow for the next week — not just the caller.

function earnSnow() external canFarmSnow {
// @> s_earnTimer is global — shared across ALL users
if (s_earnTimer != 0 && block.timestamp < (s_earnTimer + 1 weeks)) {
revert S__Timer();
}
_mint(msg.sender, 1);
s_earnTimer = block.timestamp; // @> resets the timer for everyone
}

Risk

Likelihood:

  • Every call to earnSnow by any user triggers the lockout for all other users

  • A single malicious user calling earnSnow once per week ensures no one else can ever earn free Snow

Impact:

  • All other users are locked out of free Snow minting for one week per call

  • During the 12-week farming period, only ~12 total free mints can occur across the entire user base

Proof of Concept

function testNewUserCanEarnSnow() public {
vm.prank(victory);
snow.earnSnow();
assert(snow.balanceOf(victory) == 1);
vm.prank(ashley);
snow.earnSnow();
assert(snow.balanceOf(ashley) == 1);
}

Recommended Mitigation

+ mapping(address => uint256) private lastEarned;
function earnSnow() external canFarmSnow {
- if (s_earnTimer != 0 && block.timestamp < (s_earnTimer + 1 weeks)) {
+ if (lastEarned[msg.sender] != 0 && block.timestamp < (lastEarned[msg.sender] + 1 weeks)) {
revert S__Timer();
}
+ lastEarned[msg.sender] = block.timestamp;
_mint(msg.sender, 1);
- s_earnTimer = block.timestamp;
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 12 days 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!