earnSnow()
function is designed to allow users to claim 1 free SNOW token every 7 days as part of a weekly earning mechanism during the farming period.Issue:
The contract uses a global timestamp (s_earnTimer
) to control the cooldown for all users, instead of tracking cooldowns per individual address. As a result, anyone can earn tokens using new wallets with no restriction, allowing attackers to bypass the 1-per-week rule and claim repeatedly from many EOAs.
Likelihood: High
This occurs whenever a user generates a new wallet address and calls earnSnow()
, since the contract does not track earning history on a per-user basis.
Users can automate the creation of fresh EOAs using scripts or bots to repeatedly claim Snow tokens with no penalty or cooldown enforcement, making this attack both practical and scalable.
Impact: Medium
Users can farm an unlimited number of Snow tokens by repeatedly calling earnSnow()
from new wallets, completely bypassing the intended "1 token per week" restriction.
The SNOW token supply becomes inflated beyond the design parameters, damaging the tokenomics and fairness of the protocol. This may also reduce the value of Snowman NFTs tied to SNOW ownership and weaken overall trust in the system.
The PoC demonstrates that an attacker can bypass the weekly earning restriction by calling earnSnow()
from multiple freshly generated wallets. Since the contract uses a shared global cooldown timer, each wallet is treated as a new claimant, allowing the attacker to mint unlimited SNOW tokens in a single farming window.
The contract should track the weekly earning cooldown per user address, not globally.
By using a mapping(address => uint256)
to store individual user timestamps, each address can earn SNOW once every 7 days, as originally intended.
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.
The contest is complete and the rewards are being distributed.