Using Merkle Trees in Solidity

mbvissers.eth
BLOCK6
Published in
3 min readSep 19, 2022

--

Creating and verifying Merkle Tree proofs using Solidity smart contracts and JavaScript.

Photo by Jeroen den Otter on Unsplash

Merkle Trees are a great cryptographic way to gain a certain proof. For example, that a smart contract function call has come from your own website, or that an NFT mint function call comes from a whitelisted address.

In this article we will explore the possibilities of merkle trees in Solidity using OpenZeppelin’s MerkleProof contract and our own NodeJS server with MerkleTreeJS.

You could alternatively use ECDSA hashes when only one value should be proven, unlike Merkle Trees where all ‘leaves’ can be proven.

Server-side

We cannot have a working smart contract create the Merkle Proofs if we cannot first create Merkle Trees and their proofs. For this I will use NodeJS with MerkleTreeJS. Let’s start by installing the packages we need.

npm init -y
npm install merkletreejs keccak256

To create a merkle tree, we need to import the package and create a list that will become our ‘leaves’. These leaves of raw data will be hashed using keccak256.

Here we import the packages and hash our leaves. We can now make our Merkle tree by passing our leaves and the hash function to it.

We can now visualize the tree if we want to by running tree.toString() . It will then return the tree in a nice readable format. The only thing we actually need though, is the root of the tree. We get that by calling .getRoot() . And since Solidity needs it in hex, we will also convert it to hex.

We now have everything we need to let our smart contract verify the proof. But I will still show you how to verify it in JavaScript as well. We only need to hash a value with the same hashing function, get the proof, and verify it.

In a real world application you would follow the following steps to securely generate the hash and send it to your contract:

  1. Ethereum address clicks button to mint (or anything else).
  2. Client asks server via API to generate a proof of the user’s address.
  3. Server returns proof to client.
  4. Client-side calls smart contract with web3js and passes the proof as parameter to the contract’s function.

Since every project uses a different back-end with different API structures, I will not go over how to do that in this article. But now, let’s head over to the contract side.

Contract-side

To keep this article minimal, I will be using Remix to quickly create and test the smart contract on a virtual blockchain.

We will be using the OpenZeppelin v4 MerkleProof contract to verify our proof. So let’s start by importing it in our smart contract.

The next thing we need to do, is somehow get our tree’s root inside the contract. And finally, we need to create a function that verifies the proof we get from the server. This function either reverts or returns true .

Now, for this example, we do need to manually copy the proof hash and paste it into remix to verify that it works. Or you can continue on your own and deploy the contract and create an API to call it. Good luck!

Conclusion

Thank you so much for reading and have an excellent day.

Consider supporting me by getting a Medium membership. It helps me out a lot, it won’t cost you anything extra, and you can read as many Medium articles as you like!

Follow me on Twitter and gm.xyz to keep up with me and my projects.

Check out Pixel Pizzas on the Polygon Blockchain.

You can buy me a coffee on Ko-fi!

JOIN DISCORD

Contents distributed by Learn.Block6.tech

👉 Discord — Live Talks

👉 Twitter — Latest articles

👉 LinkTr.ee

--

--

mbvissers.eth
BLOCK6

I occasionally write about programming. Follow me on Twitter @0xmbvissers