Snowman Merkle Airdrop

First Flight #42
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: low
Valid

Global Timer Lock Prevents Fair Access to earnSnow()

Summary

The s_earnTimer state variable is globally shared across all users, meaning that once any user calls buySnow() or earnSnow(), it prevents all other users from earning Snow for at least 1 week.

Description

s_earnTimer is updated every time buySnow() or earnSnow() is called.
The earnSnow() function requires that 1 week has passed since the last time s_earnTimer was updated.
As a result, one user can grief all other users by repeatedly calling buySnow() or earnSnow() and resetting the timer.

POC

function testGlobalLockPOC() public {
vm.prank(ashley);
snow.earnSnow();
vm.expectRevert();
vm.prank(jerry);
snow.earnSnow();
assert(snow.balanceOf(ashley) == 1);
assert(snow.balanceOf(jerry) == 0);
vm.warp(block.timestamp + 1 weeks);
vm.startPrank(victory);
snow.buySnow{value: FEE}(1);
vm.stopPrank();
vm.expectRevert();
vm.prank(jerry);
snow.earnSnow();
assert(snow.balanceOf(ashley) == 1);
assert(snow.balanceOf(victory) == 1);
assert(snow.balanceOf(jerry) == 0);
}

Impact

DoS (Denial of Service) on legitimate users trying to call earnSnow().
Prevents intended fair access.
Encourages monopolization by bots or whales.

Severity

HIGH

Likelihood

HIGH

Recommendation

Each user should have an independent cooldown.
Replace global timer with per-user timers, e.g. map address to timestamp:
mapping(address => uint256) public userEarnTimer;

Updates

Lead Judging Commences

yeahchibyke Lead Judge 5 months ago
Submission Judgement Published
Validated
Assigned finding tags:

buying of snow resets global timer thus affecting earning of free snow

When buySnow is successfully called, the global timer is reset. This inadvertently affects the earning of snow as that particular action also depends on the global timer.

Support

FAQs

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