claimSnowman builds the Merkle leaf from the live balance at claim time, so any balance change after the tree snapshot permanently locks legitimate users out of their claim.
SnowmanAirdrop.claimSnowman builds the Merkle leaf from i_snow.balanceOf(receiver) at claim time and transfers exactly that live balance. The Merkle tree, however, was generated from a snapshot of balances at one point in time.
Likelihood: High
Impact: If a user's Snow balance changes at all after the tree is generated — earning 1 Snow via earnSnow, buying, receiving or sending any amount — their proof no longer matches any leaf and the claim reverts, permanently locking a legitimate user out of the airdrop. The claim amount is whatever the balance happens to be at claim time rather than the snapshot amount the tree was built for, so eligibility is fragile for every single claimer.
Generate the Merkle tree from a snapshot where user U holds amount A of Snow.
Before claiming, U earns 1 Snow via earnSnow (or receives/sends any amount), so U's live balance is no longer A.
U calls claimSnowman with the valid Merkle proof and signature for (U, A).
The contract builds the leaf from the live balance (A+1) instead of A, the proof fails verification, and the call reverts — U can never claim.
Take the claim amount as a parameter, build the leaf from (receiver, amount) as passed, verify it against the root, and transfer exactly that amount. The tree's snapshot values then stay authoritative regardless of later balance movements.
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.