Skip to content

Add airdrop distribution contract for token drops to recipient lists #30

Description

@prodbycorne

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

  • contracts/airdrop-distributor/ contract created
  • Merkle proof verification implemented using SHA-256 leaf hashing
  • claim validates proof before transferring tokens
  • reclaim_unclaimed only callable after expiry_ledger
  • is_claimed getter implemented
  • Factory can deploy airdrop contracts (or separate deployment)
  • Tests: valid claim, duplicate claim, invalid proof, expired airdrop, reclaim

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official CampaignfeatureNew feature or capability

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions