In a typical Merkle-based airdrop, off-chain data (such as token balances at a snapshot in time) is used to construct a Merkle tree. This tree is later verified on-chain using the user's claimed data and a Merkle proof.
In this contract, the claimSnowman() function derives the user's token amount on-chain using i_snow.balanceOf(receiver). This approach can introduce a mismatch between the on-chain calculation and the off-chain snapshot used to generate the Merkle root.
Likelihood:
his issue will occur when a user's current token balance differs from their balance at the Merkle snapshot (e.g., they transferred tokens in or out after the snapshot).
Users who are eligible based on the snapshot but later modify their balance (even temporarily) will fail both Merkle and EIP-712 signature checks.
Impact:
Eligible users may be permanently unable to claim their airdrop allocation.
Airdrop campaign may lose trust or fail to meet its distribution goals due to false negatives in verification.
Scenario:
The user was eligible to claim with a balance of 1000 tokens at the time of the snapshot. After the snapshot:
The user transfers tokens and their balance becomes 1500.
The contract calls balanceOf(user) during claimSnowman(), which returns 1500.
The on-chain code generates a new leaf:
This new leaf does not match the one used to build the original Merkle tree (based on 1000).
As a result, MerkleProof.verify(...) fails and the claim is rejected, even though the user was legitimately included in the snapshot.
These changes ensure that the amount used for Merkle and signature validation matches the original off-chain data used to construct the Merkle root.
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.