UtilityToolsLab

© 2026 UtilityToolsLab. Built and maintained by the UtilityToolsLab Team.

Free eBooks·About·Changelog·Privacy Policy·Terms of Service·Report a bug
HomeSmart Contracts & EVMMerkle Tree Builder

Related Tools

Function SelectorGas Fee CalculatorENS NamehashABI Encoder

Merkle Tree & Proof Builder

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.

You Might Also Like

All Smart Contracts & EVM

Function Selector

Compute the 4-byte Ethereum function selector from a Solidity signature using Keccak-256, entirely in your browser. Paste names or types.

Gas Fee Calculator

Calculate Ethereum gas fees in ETH and USD. Supports EIP-1559 (base fee + tip) and legacy gas price. Six transaction type presets included.

ENS Namehash

Compute the ENS namehash (EIP-137) for any .eth domain, label by label, using Keccak-256 in your browser. See every recursive hashing step.

ABI Encoder

Encode a Solidity function call to calldata or decode raw calldata to typed values. Supports uint/int, bool, address, bytesN, bytes and string. No upload.

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.

Walkthrough: Six Addresses Down to One Root

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.

The Algorithm: Sort, Hash, Promote

  • Leaves. In Address mode the 40 hex characters are read as 20 raw bytes and hashed, matching 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.
  • Parents. With Sorted pairs selected the two children are compared byte by byte and the smaller one goes first, so the parent is keccak256(min(a,b) ‖ max(a,b)). That symmetry is what lets a verifier skip the left/right position bits entirely.
  • Odd rows. A leftover node is promoted, not duplicated. Hashing a node against itself is the classic second-preimage hole, and it also lengthens proofs for no gain.
  • Proofs. Walking up from a leaf, each level contributes its sibling, tagged 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.”
  • Ordering is load-bearing. Switching to Positional concatenates children in tree order and yields a completely different root from the same six addresses, so a root published under one setting only accepts proofs generated under that same setting.

Tricky Inputs: Odd Rows, Duplicates and a Lone Leaf

  • Paste a single line and the tree has no levels above the leaves at all. The leaf is the root, the proof is the empty array, and the panel says so: a contract verifies it with bytes32[] memory proof = new bytes32[](0).
  • A malformed line is skipped rather than silently coerced, and it names itself. Drop a character from the third address and you get “Line 3 is not a 20-byte Ethereum address — expected 40 hex characters, got 39.” The remaining entries still build a tree, so the root you see is the root of what parsed.
  • Repeating an address raises a duplicate warning, because two identical leaves share one proof and a claim contract that only marks the proof as spent would let that address collect twice.
  • Trees are capped at 1024 leaves. Paste more and the first 1024 lines are hashed, with the overflow reported rather than dropped quietly. The leaf list on screen shows 40 rows at most, but the JSON export still carries a proof for every entry.
  • Case does not matter in Address mode: input is lowercased before the bytes are read, so an EIP-55 checksummed address and its all-lowercase twin produce the same leaf, exactly as abi.encodePacked would on chain.
Leaf encoding
Pair ordering

keccak256 of the 20 raw address bytes — abi.encodePacked(address)

6 leaf nodes · depth 3
Merkle root
0xbb6bdf0123c33cd34a65d466c223b32cd1a009280d8a1ca9414ad0c10a979da4
6 leaves3 levels above the leaves3 hashes per proofOpenZeppelin-compatible
Pick a leaf to prove
Proof for leaf 0

0xB8C99b58a8c5612a6fc965Bd8ac57225E337Bb37

  • right0xad15da5a213fbd1032979ee2347e6fd3fcd01f148e632f13221c91d201dcae36
  • right0x4f69b73461947ff2a28400f31f3cd07f36fba458d7aa1d161268ffdc48648819
  • right0x8a70ed024786093360524f60ce476cc234aebd07f3883e1e45bd54e917f0c899

Folded 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.