Snowman Merkle Airdrop

First Flight #42
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Global `Snow::s_earnTimer` Prevents Multiple Users from Claiming earnSnow Independently once a week.

[H-1] Global Snow::s_earnTimer Prevents Multiple Users from Claiming earnSnow Independently once a week.

Description: The Snow::earnSnow() function uses a single uint256 private Snow::s_earnTimer state variable to enforce a cooldown period for earning Snow tokens. However, this timer is global, meaning once any user calls Snow::earnSnow(), no other user can call it again until 1 week has passed, regardless of their individual activity. This introduces severe limitations in a multi-user environment.

Impact:

  • Only one user can call Snow::earnSnow() every 7 days.

  • All other users will be reverted with Snow::S__Timer() even if they never called the function before.

  • This breaks the expected functionality of a decentralized system where users should act independently.

  • Severely restricts adoption and usability.

Proof of Concept: Add this into your TestSnow.t.sol

function testCanEarnSnowOnceAWeek() public {
vm.prank(ashley);
snow.earnSnow();
assert(snow.balanceOf(ashley) == 1);
vm.prank(jerry);
vm.expectRevert();
snow.earnSnow(); // Reverts due to global cooldown
}

Here, jerry is prevented from calling Snow::earnSnow() immediately after ashley, even though jerry has never interacted before.

Recommended Mitigation: Change Snow::s_earnTimer from a single global variable to a per-user mapping:

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

Lead Judging Commences

yeahchibyke Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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