Merkle

Storage & deploys

merkle tree builder

Build a Merkle tree for an airdrop or allowlist: get the root, a proof for any address, a Solidity verify snippet and downloadable tree.json and proofs.json. Byte-for-byte compatible with OpenZeppelin StandardMerkleTree and MerkleProof.

runs in your browser
try
merkle root · 4 leaves
0x6bbb0434396b2fa30dfbb97be5727dfcc2773c41696182ff6de555e022e14f85
proof for one row
line 2: 0x2222222222222222222222222222222222222222, 2500000000000000000
0xb92c48e9d7abe27fd8dfd6b5dfdbfb1c9a463f80c712b66f3a5180a090cccafcleaf hash
proof (bytes32[])
["0x2875f5093aafcdd988e50894a94909fffb5c813a816cb7684b0652bc7a9ef946", "0xcc68be0fb07973d30b0b70c7c3758f8a4cf464921f9ed8b1be9c22170e2d78b7"]
verify it in solidity
openzeppelin MerkleProof
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; bytes32 public constant ROOT = 0x6bbb0434396b2fa30dfbb97be5727dfcc2773c41696182ff6de555e022e14f85; function claim(address account, uint256 amount, bytes32[] calldata proof) external { bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(account, amount)))); require(MerkleProof.verify(proof, ROOT, leaf), "not on the list"); // ... }

good to know

is it compatible with openzeppelin?

yes: leaves are keccak256(bytes.concat(keccak256(abi.encode(...)))) with sorted pairs, exactly like @openzeppelin/merkle-tree, and tree.json loads with StandardMerkleTree.load.

why the double hash?

hashing the leaf twice means no leaf can ever equal an inner node, which blocks the second-preimage trick on merkle proofs.