MerkleAirdrop.claim() verifies callers against a Merkle tree whose leaves are computed as keccak256(bytes.concat(keccak256(abi.encode(account, amount)))). The leaf contains only the recipient address and claim amount — no chain ID, no contract address.
A proof generated for a given (account, amount) pair is valid on any deployment of MerkleAirdrop that uses the same Merkle root, regardless of chain or contract address. If the deployer runs a testnet deployment with the same root (common practice), every legitimate recipient's proof is immediately usable to drain the testnet (or mainnet) contract. Any future multi-chain airdrop using the same root creates the same exposure.
Likelihood:
Deploying the same Merkle root on testnet and mainnet for testing is standard practice. Any proof from a testnet claim is immediately replayable on mainnet.
If the protocol ever expands to additional chains (Ethereum, Polygon, Arbitrum) using the same recipient list and root, every user who claimed on one chain can claim on all others.
Impact:
An attacker with access to a valid proof (obtained from testnet, a public claim tx, or the airdrop announcement) can drain the airdrop on any parallel deployment.
All unclaimed tokens on the second deployment can be stolen by replaying proofs observed on the first.
The test deploys two separate MerkleAirdrop contracts with identical roots (simulating testnet + mainnet with the same Merkle tree). Alice's proof from the first deployment is submitted directly to the second, draining her allocation from both contracts using one proof.
Alice's single Merkle proof works against both deployments, receiving double her intended allocation — confirming the leaf is not bound to a specific contract or chain.
Bind the leaf to both the chain ID and the contract address:
This ensures every proof is unique to the specific contract instance and chain, making cross-deployment and cross-chain replay impossible.
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.