p0mvn / cw-merkle-drop-tokenfactory

Merkle Drop App based on CosmWasm TokenFactory Smart Contract

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Merkle Drop App

Introduction

The conventional way we approach airdrops today is sub-optimal. This normally involves iterating over large data sets, is a convoluted process to actually get the token to the end user's wallet, can take multiple days to complete, and can congest the blockchain.

The way this Merkle drop contract solves this problem is in the following way:

  1. With the provided script, the process of pulling a list of accounts from live Osmosis state is now completely automated. In this implementation, we airdrop to accounts that have a user defined minimum number of osmo staked.
  • This export normally takes over two hours, however we got this process down to 30 seconds by only exporting the data required to generate the Merkle tree.
  1. Utilizing this data, our script takes the amount of tokens the user wants to airdrop and proportionally (with respect to osmo staked) distributes this to each wallet and exports this as a csv.

  2. This csv is then used to generate a Merkle tree. From this tree, the Merkle root is extracted. This is the only data that will need to get stored on chain!

  3. Now, given a user address, the frontend will determine how much this address is allocated for the airdrop. This allocation number as well as address is used to confirm the Merkle proof via the smart contract.

  4. Utilizing tokenfactory, our contract mints the coresponding airdrop amount and sends it to the requesting user.

Prerequisites

  1. Have osmosisd running as a systemctl service named osmosisd.service
  • This can be done automatically with the following command: source <(curl -sL https://get.osmosis.zone/run). Choose the full node option and at the end choose to run a osmosisd service (not a cosmovisor service for this to work out of the box)
  1. Ensure you have enough state to export the account balances at the desired height

Instructions

Clone the repo and step inside

cd $HOME
git clone https://github.com/p0mvn/merkle-drop-app.git
cd $HOME/merkle-drop-app

Give the script execution permissions

chmod +x ./helpers/create-csv.sh

Run the script. Without any inputs, this will give you a csv of all accounts that have staked greater than 0 OSMO at the latest block height you have on your full node.

./helpers/create-csv.sh

Optionally, you can provide two inputs: the minimum staked amount and the export height. In the following example, this provides a csv of all accounts have staked 1000 OSMO or more on block height 4000000.

./helpers/create-csv.sh 1000000000 4000000

This provides you with the final airdrop file in the following location:

cat ~/.osmosisd/airdrop.csv

Interacting with The Contract

Deploy and Instantiate

Beaker

beaker wasm deploy merkle-drop --signer-account test1 --no-wasm-opt --raw '{ "merkle_root": "1V0YcwzXWtB+iuOTob6juiNliUmB278xZIKMnzwjqOU=" }' --label 1

Manual

# Store Code
TX=$(osmosisd tx wasm store target/wasm32-unknown-unknown/release/merkle_drop.wasm --from lo-test1 --keyring-backend test --chain-id=localosmosis --gas-prices 0.1uosmo --gas auto --gas-adjustment 1.3 -b block --output json -y | jq -r '.txhash')
CODE_ID=$(osmosisd query tx $TX --output json | jq -r '.logs[0].events[-1].attributes[0].value')
echo "Your contract code_id is $CODE_ID"

# Instantiate
osmosisd tx wasm instantiate $CODE_ID '{ "merkle_root": "1V0YcwzXWtB+iuOTob6juiNliUmB278xZIKMnzwjqOU=" }' --from lo-test1 --keyring-backend test --amount 50000uosmo  --label "SwapRouter Contract" --from lo-test1 --chain-id localosmosis --gas-prices 0.1uosmo --gas auto --gas-adjustment 1.3 -b block -y --no-admin

# Get Address
CONTRACT_ADDR=$(osmosisd query wasm list-contract-by-code $CODE_ID --output json | jq -r '.contracts[0]')
echo $CONTRACT_ADDR

Create TokenFactory Denom For Testing

  • create
osmosisd tx tokenfactory create-denom mydenom --from lo-test1 --keyring-backend test --chain-id=localosmosis -b=block
  • verify admin
osmosisd q tokenfactory denom-authority-metadata factory/osmo1cyyzpxplxdzkeea7kwsydadg87357qnahakaks/mydenom
  • change admin
osmosisd tx tokenfactory change-admin "factory/osmo1cyyzpxplxdzkeea7kwsydadg87357qnahakaks/mydenom" "osmo14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sq2r9g9" --from lo-test1 --keyring-backend test -b=block --chain-id=localosmosis

SetSubDenom

beaker wasm execute merkle-drop --raw '{ "set_sub_denom": { "subdenom": "mydenom" } }' --signer-account test1 --label 1

Claim

beaker wasm execute merkle-drop --raw '{ "claim": { "claimer_addr": "osmo1hqslwuc8ukaaaxfmahgnquyqx3w0tmrluwxmxj", "amount": "1421901", "proof": "[{\"is_left_sibling\":true,\"hash\":[89,79,106,114,49,69,77,102,68,119,114,48,69,84,73,103,82,71,97,108,48,79,108,53,105,56,82,103,111,57,85,51,76,70,82,90,115,66,97,78,89,51,73,61]},{\"is_left_sibling\":false,\"hash\":[80,54,110,55,43,55,72,72,111,52,109,104,79,104,102,105,108,83,43,118,87,54,88,85,88,113,48,115,105,99,83,116,116,52,112,54,119,114,68,48,113,47,73,61]},{\"is_left_sibling\":true,\"hash\":[79,79,110,66,86,100,72,56,121,84,70,57,115,78,65,56,80,85,81,97,111,71,89,119,81,89,87,83,109,71,116,89,56,79,118,85,118,98,73,83,122,74,77,61]},{\"is_left_sibling\":false,\"hash\":[102,65,68,121,57,69,49,118,56,70,78,78,81,53,109,47,50,120,78,55,103,110,119,89,78,82,104,80,83,53,69,105,79,53,115,79,77,43,118,106,50,98,56,61]}]" } }' --signer-account test1 --label 1

Other Utility Commands

Note:

  • osmo1cyyzpxplxdzkeea7kwsydadg87357qnahakaks is lo-test1 on the test keyring (Granter)
  • osmo18s5lynnmx37hq4wlrw9gdn68sg2uxp5rgk26vv is lo-test2 on the test keyring (Grantee)

AuthZ Grant

TokenFactory Mint

osmosisd tx authz grant osmo18s5lynnmx37hq4wlrw9gdn68sg2uxp5rgk26vv generic --msg-type /osmosis.tokenfactory.v1beta1.MsgMint --from lo-test1 --keyring-backend test -b=block

Bank Send

As Send Authorization (maybe in the future)
osmosisd tx authz grant osmo18s5lynnmx37hq4wlrw9gdn68sg2uxp5rgk26vv send --spend-limit=10000factory/osmo1cyyzpxplxdzkeea7kwsydadg87357qnahakaks/mydenom --from lo-test1 --keyring-backend test --chain-id localosmosis -b=block
As Generic Authorication
osmosisd tx authz grant osmo18s5lynnmx37hq4wlrw9gdn68sg2uxp5rgk26vv generic --msg-type /cosmos.bank.v1beta1.MsgSend --from lo-test1 --keyring-backend test --chain-id localosmosis -b=block

Mint as Granter

osmosisd tx tokenfactory mint 10factory/osmo1cyyzpxplxdzkeea7kwsydadg87357qnahakaks/mydenom --from lo-test1 --keyring-backend test -b=block --chain-id=localosmosis

Generate Mint Transaction

osmosisd tx tokenfactory mint 10factory/osmo1cyyzpxplxdzkeea7kwsydadg87357qnahakaks/mydenom --from osmo1cyyzpxplxdzkeea7kwsydadg87357qnahakaks --generate-only > testdata/mint_tx.json

Run The AuthZ Grant as Grantee

osmosisd tx authz exec testdata/mint_tx.json --from lo-test2 --keyring-backend test -b=block

Query Grants

osmosisd q authz grants osmo1cyyzpxplxdzkeea7kwsydadg87357qnahakaks osmo18s5lynnmx37hq4wlrw9gdn68sg2uxp5rgk26vv

About

Merkle Drop App based on CosmWasm TokenFactory Smart Contract


Languages

Language:Rust 52.2%Language:TypeScript 44.2%Language:JavaScript 1.9%Language:Shell 1.2%Language:CSS 0.6%