s_earnTimer is one global variable shared by all users, so the weekly free earn is once-per-week for the whole protocol and a single griefer can reset it forever.
Snow.s_earnTimer is a single state variable shared by all users. earnSnow requires block.timestamp > s_earnTimer + 1 weeks and resets it; buySnow also resets it.
Likelihood: High
Impact: The free weekly earn is effectively once-per-week for the ENTIRE protocol, not per user — only one user worldwide can earn in any given week. Worse, any single actor can grief the whole protocol by calling earnSnow (or buySnow) every week, perpetually resetting the timer and denying every other user the only free Snow acquisition path, at the cost of one cheap transaction per week.
User A calls earnSnow and receives the weekly Snow; the global s_earnTimer resets.
Every other user calling earnSnow in the same week reverts, even though they have never earned.
A repeats this (or calls buySnow) every week, so no other user can ever use the free earn path.
Make the timer per-user: mapping(address => uint256) s_earnTimer, checked and set for msg.sender only; buySnow should not touch the earn timer.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.