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 over 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Appeal created

the2ke Submitter
over 1 year ago
yeahchibyke Lead Judge
over 1 year ago
the2ke Submitter
over 1 year ago
yeahchibyke Lead Judge
over 1 year ago
yeahchibyke Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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

Give us feedback!