Snowman Merkle Airdrop

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

Shared Global Cooldown Prevents Individual Minting

The s_earnTimer variable is declared as a single global value, shared by all users causing a flawed cooldown mechanism.

Description

  • the earnSnow() function is designed to allow evry user to mint a Snow token for free every week. To enforce this limit, there is a variable s_earnTimer that tracks every user last token minted time, ensuring that every user mints one time every week.

  • The cooldown is implemented using a single global variable, s_earnTimer, which is shared by all users. . This means that once any user calls earnSnow(), the cooldown applies to everyone, preventing others from minting until the global timer resets. This break the main functionnality of the function.

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

Risk

Likelihood:

  • This issue occurs whenever any user successfully calls the earnSnow() function, as the shared s_earnTimer is immediately updated and affects all subsequent calls.

Impact:

  • Only one user is able to mint tokens during each cooldown cycle, effectively creating a monopoly on token distribution.


Proof of Concept

Here is a scenario :

1 - Ashley calls earnSnow() and get her SNOW Token minted and will have to wait for 1 week before earning another SNOW.

2 - Jerry does the same after Ashley called the function earnSnow() but at his turn the function revert while he should have received the token.

Run the test bellow to have a clear understanding:

function testCantEarnSnow() public {
vm.prank(ashley);
snow.earnSnow();
assert(snow.balanceOf(ashley) == 1);
// This revert because the earnTimer is shared with every users
vm.prank(jerry);
vm.expectRevert();
snow.earnSnow();
}

Recommended Mitigation

The contract should track the cooldown timer individually for each user by replacing the single global s_earnTimer variable with a mapping from user addresses to their respective timestamps.

- uint256 private s_earnTimer;
+ mapping(address => uint256) private s_earnTimer;
Updates

Lead Judging Commences

yeahchibyke Lead Judge 11 days ago
Submission Judgement Published
Invalidated
Reason: Design choice

Appeal created

the2ke Submitter
10 days ago
yeahchibyke Lead Judge
10 days ago
the2ke Submitter
10 days ago
yeahchibyke Lead Judge
9 days ago
yeahchibyke Lead Judge 8 days ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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