Skip to main content
The Claimdrop Contract V1 distributes tokens to recipients using a Merkle tree (proof-based claims). The Merkle root is stored on the campaign and used to verify proofs submitted by recipients.

Features

  • Merkle-tree based distribution
  • Lump sum and/or linear vesting distribution (two distribution types can be used simultaneously)
  • Linear vesting may include an optional cliff
  • One campaign per contract
  • Campaign can be closed to retrieve unclaimed funds and restart with a new contract/campaign

Generating airdrop data

You can generate the merkle root and proofs using the JS scripts in the contract repository.
  1. Prepare a CSV file (header required) with columns: contract_addr,address,amount.
contract_addr,address,amount
mantra1j28m8g0afvfr23423k5wypfykqrxsu94xhxvxdeyrfc4jkqm7zhqckdf5w,mantra1x5nk33zpglp4ge6q9a8xx3zceqf4g8nvaggjmc,100
mantra1j28m8g0afvfr23423k5wypfykqrxsu94xhxvxdeyrfc4jkqm7zhqckdf5w,mantra1rj2n3hge32n5u6zzw0u7clrys76srapulsvv39,200
mantra1j28m8g0afvfr23423k5wypfykqrxsu94xhxvxdeyrfc4jkqm7zhqckdf5w,mantra18mv5sz7nj2arpsqjc2aeslhh3v475np8ng6tt5,300
mantra1j28m8g0afvfr23423k5wypfykqrxsu94xhxvxdeyrfc4jkqm7zhqckdf5w,mantra16qtk5fnm4se6362yaah0scdmatx0qvp70fhej2,400
  1. Generate:
  • node merkle_root.js → generates the merkle root
  • node merkle_proof.js → generates the proofs
Only a single claim entry per address should exist in the CSV. If an address has multiple entries, consolidate them first.

How it works

  • Contract owner can create a campaign (optionally appointing a different campaign owner).
  • Campaign owner can top up a campaign before it ends.
  • Users claim by submitting a valid Merkle proof.
  • Contract owner or campaign owner can close a campaign, returning unclaimed funds to the campaign owner.

Instantiate

{
  "owner": "mantra1..."
}
KeyTypeDescription
ownerOption<String>Contract owner. If omitted, the instantiating address becomes owner.

ExecuteMsg

ManageCampaign

Actions:
  • CreateCampaign: create a new campaign (contract owner only)
  • TopUpCampaign: add funds (campaign owner only)
  • CloseCampaign: close and refund remaining funds (contract owner or campaign owner)

CreateCampaign

{
  "manage_campaign": {
    "action": {
      "create_campaign": {
        "params": {
          "owner": "mantra1...",
          "name": "Airdrop",
          "description": "This is an airdrop description.",
          "reward_asset": { "denom": "uom", "amount": "888888888888" },
          "distribution_type": [
            { "lump_sum": { "percentage": "0.25", "start_time": 1571797419 } },
            {
              "linear_vesting": {
                "percentage": "0.75",
                "start_time": 1572402219,
                "end_time": 1573007019,
                "cliff_duration": 86400
              }
            }
          ],
          "start_time": 1571797419,
          "end_time": 1573007019,
          "merkle_root": "b32b978b07b56e8f10de1f098390407017daa61c90da6a6875ca0f2d655b6107"
        }
      }
    }
  }
}
The reward_asset must be sent with this transaction.

TopUpCampaign

{
  "manage_campaign": {
    "action": { "top_up_campaign": {} }
  }
}
Send the same denom as reward_asset. You can’t top up a closed campaign.

CloseCampaign

{
  "manage_campaign": {
    "action": { "close_campaign": {} }
  }
}

Claim

{
  "claim": {
    "total_claimable_amount": "88888",
    "receiver": "mantra1...",
    "proof": [
      "1b20d6e1fa2e464d3a94fabdf28add25b6152663aa19efe1b6da2f28f50412cd",
      "27c16d1dd47dedab5c9d394d02b507e3abd01ef11f753ffc3148b04bd1aa0487"
    ]
  }
}

QueryMsg

Campaign

{ "campaign": {} }

Rewards

{
  "rewards": {
    "total_claimable_amount": "8888",
    "receiver": "mantra1...",
    "proof": [
      "1b20d6e1fa2e464d3a94fabdf28add25b6152663aa19efe1b6da2f28f50412cd",
      "27c16d1dd47dedab5c9d394d02b507e3abd01ef11f753ffc3148b04bd1aa0487"
    ]
  }
}

Claimed

{
  "claimed": {
    "address": "mantra1...",
    "start_from": "mantra1...",
    "limit": 50
  }
}