Normal behavior:
The Snow
contract enforces a global cooldown via s_earnTimer
, allowing only one user to earn 1 SNOW token per week. This ensures fair, time-gated distribution.
The problem:
The Helper
script breaks this logic by warping block.timestamp
after each earnSnow()
call to simulate that each user earned one token weekly. In reality, this state is not achievable on-chain, yet the script collects balances and may be used to create Merkle roots based on them — leading to invalid proof generation and user claim failures.
Likelihood: Medium
This occurs any time the Helper
script is used to simulate multiple users claiming earnSnow()
in the same test run. vm.warp
is called after each user to simulate weekly eligibility.
Developers may mistakenly assume the resulting Snow balances are valid, and use them to build Merkle tree input — resulting in root/hash mismatches and broken claims on-chain.
Impact: Medium
Airdrop Merkle trees may be built using balances that are not possible to reproduce on-chain.
Users may be incorrectly included or excluded from the claim list, leading to broken proofs.
Undermines trust in the airdrop distribution and breaks compatibility between test and mainnet behavior
Proof of Concept
The PoC shows that Snow.sol
uses a global cooldown, which prevents more than one user from earning Snow tokens per week. In a real on-chain scenario, only one user can call earnSnow()
successfully during that period.
However, the Helper.s.sol
script artificially uses vm.warp
to advance time between user calls, allowing multiple accounts to appear eligible in the same test script. This creates a false token state that is not reproducible on-chain — yet those balances can be used to generate a Merkle root, which breaks claim verification in production.
Switch the global cooldown (s_earnTimer
) to a per-user cooldown mapping. This allows each user to earn 1 SNOW per 7 days without relying on global state. It removes the need for artificial time jumps in tests and aligns the script’s state with what’s actually possible on-chain.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
View preliminary resultsAppeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.