Issue and opportunity: Distributing to 10,000 addresses today means 200 mint_batch transactions of 50 recipients each, at the admin's expense, with the admin writing the orchestration themselves. mint_batch's 100-recipient cap makes the ceiling explicit. For a launchpad, "launch a token and distribute it" is one job, and the app currently does the first half.
The standard answer is a Merkle claim: the admin publishes a root on chain, recipients claim against a proof, and each recipient pays their own transaction fee. Cost to the admin is one transaction regardless of list size, and unclaimed allocations can be reclaimed after a deadline.
Fix: Add contracts/airdrop/ with initialize(token, admin, merkle_root, deadline_ledger), claim(recipient, amount, proof: Vec<BytesN<32>>) using env.crypto().keccak256, a Claimed(Address) set to prevent double claims, and reclaim_unclaimed() after the deadline. On the frontend, add an admin page that takes a CSV of address and amount, builds the tree in the browser, shows the root to publish, and exports the proof set, plus a public /airdrop/[contractId] page where a connected wallet sees its allocation and claims. Note this depends on nothing else in this wave and can proceed in parallel.
Issue and opportunity: Distributing to 10,000 addresses today means 200
mint_batchtransactions of 50 recipients each, at the admin's expense, with the admin writing the orchestration themselves.mint_batch's 100-recipient cap makes the ceiling explicit. For a launchpad, "launch a token and distribute it" is one job, and the app currently does the first half.The standard answer is a Merkle claim: the admin publishes a root on chain, recipients claim against a proof, and each recipient pays their own transaction fee. Cost to the admin is one transaction regardless of list size, and unclaimed allocations can be reclaimed after a deadline.
Fix: Add
contracts/airdrop/withinitialize(token, admin, merkle_root, deadline_ledger),claim(recipient, amount, proof: Vec<BytesN<32>>)usingenv.crypto().keccak256, aClaimed(Address)set to prevent double claims, andreclaim_unclaimed()after the deadline. On the frontend, add an admin page that takes a CSV of address and amount, builds the tree in the browser, shows the root to publish, and exports the proof set, plus a public/airdrop/[contractId]page where a connected wallet sees its allocation and claims. Note this depends on nothing else in this wave and can proceed in parallel.