This repository implements a secure and gas-efficient token airdrop using a Merkle tree for authentication of claimers. The Merkle tree enables on-chain verification that a given address and amount are eligible for the airdrop, without storing or revealing the entire list of claimers.
⚠️ Work in Progress:
This project is under active development. The code and documentation are subject to change. Use at your own risk.
- Airdrop Contract:
The smart contract (src/MerkleAirdrop.sol) allows eligible users to claim tokens by providing a valid Merkle proof and EIP-712 signature. - Merkle Tree Generation:
Scripts inscript/generate the Merkle root and proofs from a list of eligible addresses and amounts. - Testing:
Includes Foundry tests (test/MerkleAirdrop.t.sol) to verify the airdrop logic and edge cases.
-
Prepare the Airdrop List:
Create a JSON file with addresses and token amounts eligible for the airdrop. -
Generate Merkle Tree & Proofs:
Use the provided scripts to generate the Merkle root and proofs for each claimer. -
Deploy the Airdrop Contract:
Deploy theMerkleAirdropcontract with the Merkle root and the token address. -
Claim Process:
Eligible users call theclaimfunction with their address, amount, Merkle proof, and EIP-712 signature to receive their tokens.
Gas sponsoring allows a third party (the "gas payer") to submit a claim transaction on behalf of an eligible user. This is useful when the user does not have ETH to pay for gas, or when a service wants to sponsor the claim process for its users.
-
Signature-Based Authorization:
The MerkleAirdrop contract requires an EIP-712 signature from the eligible user, authorizing the claim for a specific amount. This signature can be generated off-chain by the user and given to the gas payer. -
Anyone Can Submit:
Anyone (not just the user) can call theclaimfunction, as long as they provide:- The user's address
- The claim amount
- The correct Merkle proof
- The valid EIP-712 signature from the user
-
Security:
The contract verifies that:- The Merkle proof is valid for the user and amount
- The signature matches the user's address and amount
- The claim has not already been made
- User signs a claim message (off-chain) for their address and amount.
- Gas payer collects the signature and Merkle proof from the user.
- Gas payer submits the claim by calling the contract's
claimfunction, paying the gas. - User receives tokens directly to their address.
Suppose Alice is eligible for the airdrop but has no ETH. She signs the claim message and sends it to Bob (the gas payer). Bob submits the claim on-chain, paying the gas, and Alice receives her tokens.
This pattern is supported out-of-the-box by the contract and is tested in test/MerkleAirdrop.t.sol (see testGasPayerCanClaimOnBehalfOfUser).
Note:
The signature is only valid for the specific address and amount, and can only be used once. This prevents replay attacks and double claims.