How To Create A SEP-41 Token Airdrop Using A Merkle Tree

In this tutorial we will be creating a SEP-41 token and distributing it to a curated list of recipients using a merkle tree.

James On YouTube

We will start by collecting a list of addresses who are currently using Stellar’s SDEX, then we will form these into a merkle tree and store the merkle root and proofs (more on how this works below).

We will then deploy a SEP-41 token contract using OpenZeppelin standards with a built in claim function so those wallets that previously interacted with SDEX can claim their tokens.

Finally we will put together a little frontend to provide a user interface for our lucky recipients. Lets go.

All the code is open-source and available on Github: https://github.com/jamesbachini/Stellar-Airdrop-Token

I’ll be using OpenZeppelin libraries for this which were originally based on the work by Philip Liu.


Curating The Airdrop Recipients

There are a million and one ways you can put together a list of recipients. I decided to use Stellar SDEX users as I had some code I had used previously which could be modified.

git clone https://github.com/jamesbachini/Stellar-Airdrop-Token.git
cd build-list
cargo run

This will output a list of SDEX users and there is a hard coded amount value in the build-list/src/main.rs file which includes decimals. You can adjust this if you have different criteria or factors influencing how much each users gets.

The script will output a JSON file in the following format:

[
  {
    "address": "GCCVUYBUSWH4H3RTBPWEY63SGHUDIHHGGJCFLCQOWFYFWD2FSRZOQVC7",
    "amount": 1000000000
  },
  {
    "address": "GCX3AXMOAISB2ET4EVU2E2GVR332HQYBMCGAXS5TNOHSJDK4NMQPQRVJ",
    "amount": 1000000000
  }
]

Once we have our recipient list we can build the merkle tree.


Creating A Merkle Tree

Merkle trees are used to verify large amounts of data on-chain. Because decentralized storage is relatively expensive we can store a single hash known as the merkle root. And then users can submit proofs which are delivered via a web app or elsewhere to prove their address is included in the airdrop.

Merkle Tree Explainer

Let’s copy our recipient list in and generate the merkle root hash and list of proofs.

cd merkle
cargo run -- ../build-list/sdex-traders.json proofs.json

Here we are passing in the list of recipients in sdex-traders.json and output a merkle root to the console and the proofs to a proofs.json file.

Now let’s deploy the token contract.


Deploy An Airdrop Token

Note. This uses the OpenZeppelin Merkle_Distributor library which is not audited yet and still under security review.

The claim function is below.

pub fn claim(e: &Env, index: u32, receiver: Address, amount: i128, proof: Vec<BytesN<32>>) {
    receiver.require_auth();
    let data = Receiver { index, address: receiver.clone(), amount };
    Distributor::verify_and_set_claimed(e, data, proof);
    Base::mint(e, &receiver, amount);
}

So we are sending across our address, the amount and the proofs (as a vector). We then check to ensure the receiver is who they say they are with require_auth(). Then we check the data and proofs before minting the tokens direct to the recipients wallet.

We can deploy this to testnet using the stellar-cli

Deploy Stellar Contract

Note the way we pass in the merkle root as a named constructor argument after a — separator.


Creating A Web3 UI

This UI is based forked from Philip Liu’s example here.

We need to update frontend/.env.example and save it as .env

When adding the proofs.json data I flattened the file removing any whitespace and line breaks.

I also added the contract address to frontend/src/packages/contract.ts

You can run this locally with

cd frontend/
npm install
npm run dev

Go ahead and claim some tokens but only if your address is in that merkle tree.


Get The Blockchain Sector Newsletter, binge the YouTube channel and connect with me on Twitter

The Blockchain Sector newsletter goes out a few times a month when there is breaking news or interesting developments to discuss. All the content I produce is free, if you’d like to help please share this content on social media.

Thank you.

James Bachini

Disclaimer: Not a financial advisor, not financial advice. The content I create is to document my journey and for educational and entertainment purposes only. It is not under any circumstances investment advice. I am not an investment or trading professional and am learning myself while still making plenty of mistakes along the way. Any code published is experimental and not production ready to be used for financial transactions. Do your own research and do not play with funds you do not want to lose.


Posted

in

, , , , ,

by