The earnSnow
function in Snow.sol
uses a global timer variable s_earnTimer
that is shared across all users, creating a critical design flaw that prevents fair token distribution. When any user calls earnSnow()
or buySnow()
, the global timer is updated, blocking all other users from earning free tokens for the next week.
In Snow.sol
:
The timer is also updated in buySnow()
, further complicating the issue. This design means that in best-case scenario only one user per week across the entire protocol can earn free tokens, while all others are forced to purchase tokens with ETH/WETH. In the worst-case scenario, no free tokens can be distributed if the function buySnow()
is called more than once a week.
Natural blocking scenario:
Alice calls earnSnow()
on day 1, successfully mints 1 token
s_earnTimer
is set to current timestamp
Bob tries to call earnSnow()
on day 2, transaction reverts with S__Timer()
error
All users are blocked from earning tokens until day 8
Intentional denial of service:
Attacker monitors the blockchain for successful earnSnow()
calls
Exactly 7 days later, attacker immediately calls earnSnow()
or makes a minimal buySnow()
purchase
This resets the global timer, blocking legitimate users for another week
Attacker can repeat this indefinitely with minimal cost
Only 1 user per week across the entire protocol can earn free tokens, violating the intended design
Any user can block all others from earning tokens for a full week
Implement individual user timers instead of a global timer to allow each user to earn tokens independently
And delete timer update in buySnow()
When buySnow is successfully called, the global timer is reset. This inadvertently affects the earning of snow as that particular action also depends on the global timer.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.