Generate Merkle trees and cryptographic proofs for verification
A Merkle tree is a cryptographic data structure that allows efficient and secure verification of large data sets. It's fundamental to blockchain technology and is used extensively in smart contracts for allowlists, airdrops, and data verification.
A Merkle tree is a binary tree where:
Root
/ \
H01 H23
/ \ / \
H0 H1 H2 H3
| | | |
L0 L1 L2 L3
(Leaf Data)
Verify a single element is part of the set using only logâ‚‚(n) hashes, not the entire dataset.
Store only the root hash on-chain (32 bytes) instead of entire allowlists, saving massive gas costs.
Prove membership without revealing other elements in the set.
Any change to leaf data changes the root, making tampering immediately detectable.
Store thousands of allowed addresses efficiently:
Distribute tokens to specific addresses with amounts:
Prove state at a specific time:
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
contract MerkleAllowlist {
bytes32 public merkleRoot;
constructor(bytes32 _merkleRoot) {
merkleRoot = _merkleRoot;
}
function claim(bytes32[] calldata proof) external {
// Create leaf from sender address
bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
// Verify proof
require(
MerkleProof.verify(proof, merkleRoot, leaf),
"Invalid proof"
);
// Process claim...
}
}
import { MerkleTree } from 'merkletreejs';
import { keccak256 } from 'ethers/lib/utils';
// Create leaves from addresses
const addresses = ['0x123...', '0x456...'];
const leaves = addresses.map(addr => keccak256(addr));
// Build tree
const tree = new MerkleTree(leaves, keccak256, {
sortPairs: true
});
// Get root
const root = tree.getHexRoot();
// Generate proof for address
const leaf = keccak256('0x123...');
const proof = tree.getHexProof(leaf);
To verify a leaf is in the tree:
Always sort pairs before hashing to ensure consistent tree structure:
hash = keccak256(abi.encodePacked(
left < right ? left : right,
left < right ? right : left
));
Hash leaf data to prevent second preimage attacks:
// Good: Hash the data
leaf = keccak256(abi.encodePacked(address, amount));
// Bad: Use raw data
leaf = abi.encodePacked(address, amount);
Store proofs off-chain (IPFS, database) and only submit when needed for gas efficiency.