Snowman Merkle Airdrop

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

Global `s_earnTimer` in `Snow::earnSnow` restricts earning to a single user per week

Description:

The Snow::earnSnow function uses a single global timestamp (s_earnTimer) to enforce a one-week cooldown for minting new tokens. As a result, the first user to call Snow::earnSnow in a given week prevents all other users from earning Snow tokens until the cooldown expires.

function earnSnow() external canFarmSnow {
if (s_earnTimer != 0 && block.timestamp < (s_earnTimer + 1 weeks)) {
revert S__Timer();
}
_mint(msg.sender, 1);
// resets the global timer which prevents other users from earning again until one week has passed
@> s_earnTimer = block.timestamp;
}

Impact:

This limits the earning of snow tokens to only the first user who calls the Snow::earnSnow in a given week. All other users will be blocked until the This restricts Snow token earnings to only the first user who calls Snow::earnSnow within a given week.

Proof of Concept:

  1. Ashley calls the Snow::earnSnow function.

  2. The s_earnTimer is updated to the current block timestamp.

  3. Jerry attempts to call Snow::earnSnow, but the call fails because the one-week cooldown has not yet expired.

Proof of Code

function testOnlySingleUserCanEarnSnowWeekly() public {
vm.prank(ashley);
snow.earnSnow();
vm.stopPrank();
vm.prank(jerry);
vm.expectRevert();
snow.earnSnow(); // This would revert because s_earnTimer is set to the current timestamp after ashley minted
vm.stopPrank();
}

Recommended Mitigation:

To fix this, we should use a mapping instead of the s_earnTime variable to keep track of timestamp for each individual users that calls the Snow::earnSnow instead;

- 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
23 days ago
yeahchibyke Lead Judge 20 days ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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