Build a Keccak-256 Merkle tree from an address allowlist, read off the root, and copy an inclusion proof for any leaf. OpenZeppelin sorted pairs.
An allowlist of four thousand addresses will not fit inside a smart contract at any gas price worth paying. One 32-byte number does. The Merkle Tree & Proof Builder produces that number: it hashes every entry, hashes those hashes in pairs, and keeps collapsing rows until a single root is left. Each address can then prove it belongs to the list by handing the contract a short chain of sibling hashes that folds back into the same root.
The defaults match OpenZeppelin’s MerkleProof library, which is what most mint and airdrop contracts import. A leaf is keccak256(abi.encodePacked(address)). Every pair is sorted by byte value before it gets hashed, so the on-chain verifier never has to be told which sibling sat on the left. When a row has an odd node left over, that node rides up to the next row untouched rather than being paired with itself.
A holder snapshot is a list you may not want to hand to somebody else’s server. Every hash here is computed in the tab you have open, and no address ever leaves it.
Press Load Sample and six addresses drop into the box, beginning with 0xB8C99b58a8c5612a6fc965Bd8ac57225E337Bb37. Six is deliberately not a power of two. The rows collapse 6 → 3 → 2 → 1, and opening Every level, leaves to root highlights in amber the odd node each short row carries up unpaired. That first address hashes to the leaf 0x88100a24686ec35c1eb3b01fb950c5b7f8eeea66223c6b4db9ef13e3af37f67d, its proof comes out three hashes long, and the root reads 0xbb6bdf0123c33cd34a65d466c223b32cd1a009280d8a1ca9414ad0c10a979da4. Click any other row in the leaf list and the proof panel switches to that address. The button most people miss sits under the proof: Copy root + every proof as JSON gives you one object holding the root and a proof array for all six entries, keyed by address, which is the file the front end actually needs.
abi.encodePacked. Raw text hashes the line’s UTF-8 bytes instead, and Pre-hashed takes the line as a finished 32-byte leaf and hashes nothing.keccak256(min(a,b) ‖ max(a,b)). That symmetry is what lets a verifier skip the left/right position bits entirely.left or right. Fold them in order and you land on the root, which the tool re-runs on every keystroke and reports as “Folded back into the root — this proof verifies.”bytes32[] memory proof = new bytes32[](0).abi.encodePacked would on chain.keccak256 of the 20 raw address bytes — abi.encodePacked(address)
0xbb6bdf0123c33cd34a65d466c223b32cd1a009280d8a1ca9414ad0c10a979da40xB8C99b58a8c5612a6fc965Bd8ac57225E337Bb37
0xad15da5a213fbd1032979ee2347e6fd3fcd01f148e632f13221c91d201dcae360x4f69b73461947ff2a28400f31f3cd07f36fba458d7aa1d161268ffdc486488190x8a70ed024786093360524f60ce476cc234aebd07f3883e1e45bd54e917f0c899Folded back into the root — this proof verifies.
Sorted pairs is the default because OpenZeppelin's MerkleProof.verify sorts each pair before hashing, which is how it verifies a proof without being told left from right. Switching to Positional changes the root for the same addresses, so publish a root and generate its proofs under one setting only. Every hash is computed in this tab; no address list is uploaded.