Merkle Eligibility
This page explains how to use our Merkle Eligibility module.
The Merkle eligibility module was set up to allow a predefined array of criteria to be defined that is then validated against in a precursory check, before the token can be deemed eligible.
This module was primarily developed to allow for ENS domains to be deemed eligible, or ineligible, though there are more use-cases available. For the purpose of this document I will be applying the logic to that of the ENS flow implemented.
The reason that a merkle approach is required for ENS is that the name of the token cannot be extracted from the token itself. This would mean that for handling a collection such as the #10KClub (in which only numeric domains from 0000 to 9999 are included) we would not be able to apply a simple conditional statement to check the range. We also would not be able to simply define a list of immutable token IDs inside the vault as the deployment gas costs would be extremely high.
To combat this we instead only require the application of a merkle root (bytes32
) onto the contract and then require a precursory check that passes a merkle proof alongside the token ID to gauge eligibility and apply it to an internally eligibility mapping.
If you'd like to read more into the application of merkle trees on the blockchain, I'd recommend reading Using Merkle Trees for NFT Whitelists by @ItsCuzzo.
Encoding ENS domains
When working with ENS domains, we need to encode and decode them in a specific way to ensure they stay the same across the frontend website and on-chain.
In my document examples you will see regular reference to a helper function called getTokenId
that is subsequently encoded with keccak256
. This creates two vital steps for ENS domains. The getTokenId
returns the tokenId
that an ENS name has. You can test this by encoding a name and checking the listing on Opensea.
Note: This method excludes the .eth
suffix.
When we then encode the return value with keccak256
we get the ENS tokenHash
. Both the tokenId
and tokenHash
, if calculated correctly, will correspond to the stored data on the ENS Subgraph.
Generating your Merkle Tree
Generating our Merkle Tree uses 2 Node JS library:
merkletreejs
keccak256
The following code flow shows how to generate an ENS-compliant merkle tree, generate the root and generate a subsequent proof for later eligibility checks. Alternatively, an online tool can be used for testing. Note, that sortPairs
must be set to True
.
We want to store our leaves in bytes32
format, which is outputted from the keccak256
encryption for consistent and gas-efficient storage.
Once we have our proof for the tokenHash
, we can call our precursory processing function. In most eligibility modules we can just directly call eligibility, but in order for our merkle tree approach to work, this function must be called at least once per token to ensure it's added to our validTokenHashes
mapping.
Once our precursory check has been run for the token and we have deemed it valid and eligible, we are ready to mint it to the vault. Internally, the vault will just check that the encoded tokenId
(creating the tokenHash
) has been mapped as valid.
To ensure that the tokenId
is correctly mapped to the tokenHash
we must convert our tokenId
to a String and then into bytes before calling keccak256
. Failure to do this results in an incorrect tokenHash
being generated.
Precursory Flow
Last updated