Snowman Merkle Airdrop

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

Global Timer in earnSnow() Enables DoS Against Free Token Claims

Root + Impact

Description:
The earnSnow() function is designed to allow users to claim 1 Snow token per week. However, the contract uses a global timestamp s_earnTimer, which resets whenever any user claims or buys Snow.

As a result, once a user claims Snow, all other users are locked out for 7 days, enabling malicious users to continuously block others from accessing the reward.


@function earnSnow() {
if (block.timestamp < s_earnTimer + 1 weeks) {
revert S__Timer();
}
s_earnTimer = block.timestamp;
_mint(msg.sender, 1 ether);
}

Risk

Likelihood:

  • Very easy to exploit by repeatedly calling earnSnow() or triggering buySnow() before others.

  • DoS can be executed by a single wallet at very low cost.

  • Affects real users in a live environment.

Impact:

  • Legitimate users unable to claim their free Snow rewards

  • Centralization of the free reward system

  • Frustration and potential user churn

  • Can be used for sybil farming by bots


Proof of Concept

// Attacker setup
while (true) {
buySnow(0.01 ether); // resets s_earnTimer globally
sleep(6 days + 23 hrs);
}
// Everyone else calling earnSnow() will revert
earnSnow(); // Reverts: S__Timer

Explanation:
Global timer design punishes all users. Since anyone can reset the timer, it enables permanent locking unless fixed.

Recommended Mitigation

- uint256 public s_earnTimer;
+ mapping(address => uint256) public s_lastEarnTime;
@function earnSnow() {
+ require(block.timestamp >= s_lastEarnTime[msg.sender] + 1 weeks, "Too soon");
+ s_lastEarnTime[msg.sender] = block.timestamp;
_mint(msg.sender, 1 ether);
}

Explanation:
Switching to a per-user claim timer ensures that each user can claim once every 7 days independently. Prevents abuse and creates a fairer, scalable reward model.

Updates

Lead Judging Commences

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

Support

FAQs

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