Hashtag Web3 Logo

Merkle Airdrop Distribution Explained

A Merkle airdrop is a highly efficient method for distributing tokens to a large number of users. This guide explains how it uses Merkle trees to save gas and simplify the airdrop process.

Merkle Airdrop Distribution Explained - Hashtag Web3 article cover

Airdrops are a powerful tool for distributing a new token to a project's community. However, airdropping tokens to thousands or even millions of addresses presents a major technical challenge: how do you do it without spending a fortune on gas fees? Sending a separate transfer transaction to each recipient is prohibitively expensive.

The industry-standard solution to this problem is the Merkle airdrop. This is a highly gas-efficient pattern that uses a cryptographic data structure called a Merkle tree to verify a user's eligibility to claim their tokens, without storing the entire list of eligible addresses on-chain.

The Problem with Naive Airdrops

Imagine you want to airdrop tokens to 100,000 eligible addresses. A simple approach would be to write a smart contract with a loop that calls transfer for each address.

// Inefficient and will fail
function airdrop(address[] calldata recipients, uint256[] calldata amounts) external onlyOwner {
    for (uint i = 0; i < recipients.length; i++) {
        token.transfer(recipients[i], amounts[i]);
    }
}

This will not work. The transaction would require so much gas to execute the loop 100,000 times that it would far exceed the block gas limit, causing the transaction to fail.

The Merkle Tree Solution: A Pull-Based Approach

A Merkle airdrop uses a "pull" instead of a "push" mechanism. Instead of the contract pushing tokens to everyone, eligible users must come to the contract to "pull" or claim their tokens. The Merkle tree is what allows the contract to verify that a user is eligible to claim, without having to store the entire list of 100,000 addresses.

The Process:

Step 1: Off-Chain - Build the Merkle Tree

  1. Create the List: First, you create a list of all the eligible addresses and the amount of tokens each is entitled to. This is your "whitelist."
  2. Hash the Leaves: Each entry in the list (e.g., address + amount) is hashed to create a "leaf" of the tree.
  3. Build the Tree: The leaves are then paired up and hashed together to create the parent nodes. This process is repeated, moving up the tree, until you are left with a single hash at the top. This is the Merkle root.

Step 2: On-Chain - Store Only the Root

The only piece of information that needs to be stored in the smart contract is the single, 32-byte Merkle root.

contract Airdrop {
    bytes32 public immutable merkleRoot;

    constructor(bytes32 _merkleRoot) {
        merkleRoot = _merkleRoot;
    }
    // ... claim function
}

This is incredibly gas-efficient. You can prove the eligibility of millions of users with just a single bytes32 hash stored on-chain.

Step 3: Off-Chain - Generate the Proof

When a user wants to claim their airdrop, they need to prove to the contract that they were part of the original whitelist that generated the Merkle root. To do this, they need a Merkle proof.

The Merkle proof is the set of "sibling" hashes that are needed to recalculate the Merkle root from the user's specific leaf hash. The user's wallet or the project's frontend can generate this proof for them.

Step 4: On-Chain - Verify the Proof and Claim

The user calls the claim function on the smart contract, providing their address, the amount they are claiming, and their unique Merkle proof.

function claim(address recipient, uint256 amount, bytes32[] calldata merkleProof) external {
    // 1. Recreate the leaf hash from the user's data
    bytes32 leaf = keccak256(abi.encodePacked(recipient, amount));

    // 2. Use the provided proof to recalculate the Merkle root
    bytes32 computedRoot = MerkleProof.processProof(merkleProof, leaf);

    // 3. Verify that the recalculated root matches the one stored in the contract
    require(computedRoot == merkleRoot, "Invalid proof.");

    // ... (also check that the user hasn't claimed before) ...

    // 4. If valid, transfer the tokens
    token.transfer(recipient, amount);
}

The smart contract does not need to know the entire list of addresses. It only needs to perform one simple check: does the proof provided by this specific user, combined with their data, result in the same Merkle root that is stored in the contract? If it does, the user is verified, and the tokens are released.

Why It's So Efficient

  • Minimal On-Chain Storage: You only store a single 32-byte hash, regardless of whether you have 100 or 10 million eligible users.
  • Shifts Gas Costs to Users: The gas cost of claiming is borne by the individual users who choose to claim, rather than by the project having to pay for 100,000 separate transactions.

The Merkle airdrop is a clever and powerful cryptographic pattern that is essential for any project looking to do a large-scale, gas-efficient token distribution on the blockchain.


Frequently Asked Questions

1. What is a Merkle tree?

A Merkle tree is a data structure where each "leaf" node is a hash of a piece of data, and each "branch" node is a hash of its child nodes. This structure allows for the efficient and secure verification of large data sets. It is also a core component of how blockchains themselves work, as explained in our guide to Merkle trees in blockchain.

2. What is a Merkle root?

The Merkle root is the single hash at the very top of a Merkle tree. It acts as a unique and tamper-proof fingerprint for the entire dataset.

3. What is a Merkle proof?

A Merkle proof is the set of sibling hashes that a user needs to provide to prove that their specific data (their "leaf") was included in the original dataset that created the Merkle root.

4. What is a "pull" vs. "push" airdrop?

In a "push" airdrop, the project sends tokens to all recipients. This is not gas-efficient. In a "pull" airdrop, like a Merkle airdrop, users must actively come to the contract to "claim" their tokens.

5. What are the prerequisites for a Merkle airdrop?

The project first needs to determine the list of eligible addresses. This is typically done by taking a snapshot of the blockchain at a specific point in time and analyzing user activity.

Looking for a Web3 Job?

Get the best Web3, crypto, and blockchain jobs delivered directly to you. Join our Telegram channel with over 58,000 subscribers.