Snowman Merkle Airdrop

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

First Caller Can Freely Mint Snow Tokens

Root + Impact

Description

earnSnow is expected to enforce a 1-week cooldown before allowing users to mint Snow tokens, ensuring rewards are distributed at controlled intervals.

The cooldown check is bypassed on the first call because s_earnTimer is initialized to 0.
When s_earnTimer == 0, the condition that reverts is skipped, allowing the first caller to mint Snow immediately and without any waiting period and without calling buySnow function.

function earnSnow() external canFarmSnow {
if (s_earnTimer != 0 && block.timestamp < (s_earnTimer + 1 weeks)) {
revert S__Timer(); // @> skipped when s_earnTimer == 0
}
_mint(msg.sender, 1);
s_earnTimer = block.timestamp;
}

Risk

Likelihood:

  • Always occurs for the first caller after deployment


Requires no special conditions or privileges

Impact:

  • First caller gains an unfair advantage


Breaks expected reward timing and fairness assumptions

Proof of Concept

add this function in testSnow.t.sol

function testCanEarnSnowWithoutBuying() public {
// we do not call buySnow
// s_earnTimer is 0, not initialize
// ashley will call earn function without buying any snow token
vm.prank(ashley);
snow.earnSnow();
// ashley succesfully earned 1 snow token without waiting 1 week and without buying snow token
assert(snow.balanceOf(ashley) == 1);
}

Recommended Mitigation

Initialize the earning timer at deployment or explicitly enforce a minimum delay before the first claim.

constructor(...) {
...
+ s_earnTimer = block.timestamp;
}
function earnSnow() external canFarmSnow {
- if (s_earnTimer != 0 && block.timestamp < (s_earnTimer + 1 weeks)) {
+ if (block.timestamp < (s_earnTimer + 1 weeks)) {
revert S__Timer();
}
...
}
Updates

Lead Judging Commences

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