A program for distributing tokens efficiently via uploading a Merkle root.
To claim via CLI instead of using https://jito.network/airdrop, run the following commands.
- Build the cli (must have rust + cargo installed):
cargo b -r- Run
claimwith the proper args. Be sure to replace<YOUR KEYPAIR>with the full path of your keypair file. This will transfer tokens from the account8Xm3tkQH581s3MoRHWUNYA5jKbgPATW4tJAAxgwDC6T6to a the associated token account owned by your keypair, creating it if it doesn't exist.
./target/release/cli --rpc-url https://api.mainnet-beta.solana.com --keypair-path <YOUR KEYPAIR> --airdrop-version 0 --mint jtojtomepa8beP8AuQc6eXt5FriJwfFMwQx2v2f9mCL --program-id mERKcfxMC5SqJn4Ld4BUris3WKZZ1ojjWJ3A3J5CKxv claim --merkle-tree-path merkle_tree.jsonNote that for searchers and validators, not all tokens will be vested until December 7, 2024. You can check the vesting status at https://jito.network/airdrop.
Follow these steps to deploy a new USDC distributor to the existing program at mERKcfxMC5SqJn4Ld4BUris3WKZZ1ojjWJ3A3J5CKxv:
- Install Solana CLI tools: https://solana.com/docs/intro/installation
- Build the CLI tool:
cargo build --release - Acquire USDC tokens from the market (total amount = sum of all amounts in your CSV)
-
Create your recipients CSV file in this format:
pubkey,amount_unlocked,amount_locked,category <recipient_pubkey_1>,<unlocked_amount>,<locked_amount>,<category> <recipient_pubkey_2>,<unlocked_amount>,<locked_amount>,<category>python generate_csv.py
-
Generate the Merkle tree from your CSV:
./target/release/cli \ --mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \ --rpc-url https://api.mainnet-beta.solana.com \ --keypair-path ~/.config/solana/id.json \ create-merkle-tree \ --csv-path airdrop_100k.csv \ --merkle-tree-path merkle_tree.jsonspl-token create-account EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
-
Create the new distributor on-chain:
./target/release/cli \ --rpc-url https://api.mainnet-beta.solana.com \ --keypair-path ~/.config/solana/id.json \ --mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \ --program-id mERKcfxMC5SqJn4Ld4BUris3WKZZ1ojjWJ3A3J5CKxv \ --airdrop-version 422 \ # a unique version (identifier) new-distributor \ --clawback-receiver-token-account CZZZeKxrQRPjwAA7REZWqsADChFY7P41K2wNmRWT779U \ --start-vesting-ts 1756239698 \ --end-vesting-ts 1756239699 \ --clawback-start-ts 1756329899 \ --merkle-tree-path merkle_tree.json
Parameters:
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v= USDC mint address (mainnet)- Timestamps are Unix timestamps (seconds since epoch)
clawback-start-tsmust be at least 1 day afterend-vesting-ts- The CLI will output the distributor vault address where you need to send tokens
-
Transfer USDC tokens to the distributor vault:
Get the vault address from the newDistributor program output, bottom of page: https://solscan.io/tx/2iHVJ8yFAhohEYzXWUedZjji99Uhrhf5qKXzYKxaqPu7cNYg4E7LKNUWoc6GiXKWgjyBfMzJUpLYBTKjMwzwhre6
spl-token transfer EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \ <TOTAL_AMOUNT> \ <DISTRIBUTOR_VAULT_ADDRESS> \ --fund-recipient
Note:
<DISTRIBUTOR_VAULT_ADDRESS>is printed by the previous command and<TOTAL_AMOUNT>is the sum of allamount_unlocked+amount_lockedfrom your CSV. -
Test claiming tokens (optional):
./target/release/cli \ --rpc-url https://api.mainnet-beta.solana.com \ --keypair-path ~/.config/solana/id.json \ --mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \ --program-id mERKcfxMC5SqJn4Ld4BUris3WKZZ1ojjWJ3A3J5CKxv \ --airdrop-version 422 \ claim \ --merkle-tree-path merkle_tree.json
- The
new_distributorinstruction is susceptible to frontrunning - Always verify the created distributor parameters match your expectations after the transaction succeeds
- Double-check the vault address before transferring large amounts of USDC
-
avm install 0.30.1 && avm use 0.30.1 -
cargo build --release -
solana-keygen new --outfile ~/.config/solana/id.json -
solana airdrop 2 --url https://api.devnet.solana.com -
cat ~/.config/solana/id.json -
Import private key to Phantom
-
Swap for dusdc on Raydium https://raydium.io/swap/
-
python generate_csv.py -
./target/release/cli --mint USDCoctVLVnvTXBEuP9s8hntucdJokbo17RwHuNXemT --rpc-url https://api.devnet.solana.com --keypair-path ~/.config/solana/id.json create-merkle-tree --csv-path airdrop_100k.csv --merkle-tree-path merkle_tree_100k.json -
RUSTUP_TOOLCHAIN=nightly-2025-04-01 anchor build -
./target/release/cli --rpc-url https://api.devnet.solana.com --keypair-path ~/.config/solana/id.json --airdrop-version 0 --mint USDCoctVLVnvTXBEuP9s8hntucdJokbo17RwHuNXemT --program-id APEosY9z2WBL8ZXj9V7L2RPwpeKb3czc3N6qqMsubuok new-distributor --clawback-receiver-token-account HViKVWxAHVeFC3ptn83xLiHYrhMgNteUSK8GqHmDjRbv --start-vesting-ts 1755720310 --end-vesting-ts 1755720311 --merkle-tree-path merkle_tree_100k.json --clawback-start-ts 1755820312 -
anchor deploy --provider.cluster devnet -
spl-token address --owner E2RL3eYMRAvvtLUNwrAE3bPuJoNTR2AvzqLSMJcbeNfB --token USDCoctVLVnvTXBEuP9s8hntucdJokbo17RwHuNXemT --verbose -
spl-token transfer USDCoctVLVnvTXBEuP9s8hntucdJokbo17RwHuNXemT 10 E2RL3eYMRAvvtLUNwrAE3bPuJoNTR2AvzqLSMJcbeNfB --allow-non-system-account-recipient