Overview
SmartDrop's core use case is token airdrops but there is no airdrop contract yet — only the farming/staking infrastructure. An AirdropDistributor contract is needed that enables an admin to register a Merkle tree of recipients and allow them to claim their allocation.
Design
Merkle Claim Model
Recipients are committed as a SHA-256 Merkle tree of (address, amount) leaves. A recipient proves eligibility by providing a Merkle proof. This scales to millions of recipients without storing them all on-chain.
AirdropDistributor
├── initialize(admin, token, merkle_root, expiry_ledger)
├── claim(user, amount, proof: Vec<BytesN<32>>)
├── reclaim_unclaimed(admin) — after expiry_ledger
├── is_claimed(user) -> bool
└── airdrop_info() -> AirdropInfo
Storage
#[contracttype]
pub enum DataKey {
Admin,
Token,
MerkleRoot,
ExpiryLedger,
Claimed(Address), // set to true when user claims
}
Claim Verification
pub fn claim(env: Env, user: Address, amount: i128, proof: Vec<BytesN<32>>) -> Result<(), AirdropError> {
user.require_auth();
if is_claimed(&env, &user) { return Err(AirdropError::AlreadyClaimed); }
if env.ledger().sequence() > get_expiry_ledger(&env) { return Err(AirdropError::Expired); }
let leaf = compute_leaf(&env, &user, amount);
if !verify_proof(&env, &proof, &get_merkle_root(&env), &leaf) {
return Err(AirdropError::InvalidProof);
}
set_claimed(&env, &user);
token::TokenClient::new(&env, &get_token(&env))
.transfer(&env.current_contract_address(), &user, &amount);
env.events().publish((symbol_short!("drop"), symbol_short!("claimed")), (user, amount));
Ok(())
}
Error Codes
AlreadyClaimed = 1, Expired = 2, InvalidProof = 3, NotExpired = 4, AlreadyInitialized = 5
Acceptance Criteria
Overview
SmartDrop's core use case is token airdrops but there is no airdrop contract yet — only the farming/staking infrastructure. An
AirdropDistributorcontract is needed that enables an admin to register a Merkle tree of recipients and allow them to claim their allocation.Design
Merkle Claim Model
Recipients are committed as a SHA-256 Merkle tree of
(address, amount)leaves. A recipient proves eligibility by providing a Merkle proof. This scales to millions of recipients without storing them all on-chain.Storage
Claim Verification
Error Codes
AlreadyClaimed = 1,Expired = 2,InvalidProof = 3,NotExpired = 4,AlreadyInitialized = 5Acceptance Criteria
contracts/airdrop-distributor/contract createdclaimvalidates proof before transferring tokensreclaim_unclaimedonly callable afterexpiry_ledgeris_claimedgetter implemented