# Merkle Distributor

### Introduction

The Merkle Distributor provides a modular and efficient solution for token distribution using merkle proofs, supporting various token standards and customizable distribution patterns.

## 🚀 Quick Start

### What is a Merkle Distributor?

A Merkle Distributor is a smart contract system that enables efficient and verifiable token airdrops. Instead of storing all recipient data on-chain, it uses a Merkle tree where only the root is stored, significantly reducing gas costs while maintaining security.

### Key Benefits

* ✅ **Gas Efficient** - Only stores Merkle root on-chain
* ✅ **Verifiable** - Claims are cryptographically proven
* ✅ **Flexible** - Supports multiple token types and distribution patterns
* ✅ **Secure** - Built with security best practices

## 📋 System Overview

### Account Structure

<figure><img src="/files/mozxLqL2Y10AjTHRr4mG" alt=""><figcaption></figcaption></figure>

### Storage Pattern

A contract has one config storage account, which stores the contract admin's account address and the default fee collector's deployment address. This account will also store a new admin's account address for secure two-step ownership transfers.

```rust
pub struct Config {
  pub admin: Pubkey,
  pub new_admin: Pubkey,
  pub default_fee_collector: Pubkey,
}
```

A Merkle Distributor deployment can manage multiple airdrops. Airdrops use the following storage pattern:

```rust
pub struct MerkleAirdrop {
  pub owner: Pubkey,
  pub root: [u8; 32],
  pub project_token: Pubkey,
  pub claim_delegate: Pubkey,
  pub start_time: u64,
  pub end_time: u64,
  pub fee_collector: Pubkey,
  pub fee_token: Pubkey,
  pub paused: bool,
  pub uri: String,
}
```

A standard time-locked claim is created with the following storage pattern:

```rust
pub struct TokenTableMerkleDistributorData {
  pub index: u64,
  pub claimable_timestamp: u64,
  pub claimable_amount: u64,
}
```

### Claim Mechanism

There are two ways to claim tokens:

1. **Direct Claim** - Recipients claim their own tokens
2. **Delegate Claim** - Authorized delegate claims for recipients

```rust
pub fn claim(
  ctx: Context<Claim>,
  project_id: String,
  leaf: [u8; 32],
  proof: Vec<[u8; 32]>,
  group: [u8; 32],
  data: TokenTableMerkleDistributorData
) -> Result<()>
```

### **Security Features**

* Reentrancy protection on all claim functions
* Double-claim prevention via leaf tracking
* Time-based access control
* Owner-only administrative functions

## 💰 Fee System

### Overview

The fee system provides flexible fee collection for claims.

### Components

1. **Fee Collector** - External `FeeCollector` program that calculates and manages vault accounts
2. **Fee Token** - Native or SPL token for fees
3. **Vault Accounts** - Program Derived Accounts (PDAs) for holding fee tokens

## 🔒 Security

### Access Control

| Role          | Permissions                                                         |
| ------------- | ------------------------------------------------------------------- |
| Program Admin | Set fee collector, transfer program admin                           |
| Airdrop Owner | Set airdrop parameters, withdraw tokens, transfer airdrop ownership |
| Delegate      | Claim on behalf of recipients                                       |
| Users         | Claim their allocated tokens                                        |

### Security Features

* **Reentrancy Guards** - All state-changing functions protected
* **Leaf Tracking** - Prevents double claims
* **Time Windows** - Enforced distribution periods
* **Proof Verification** - Cryptographic claim validation

## 📡 Events & Errors

### Events

| Event              | Description                      |
| ------------------ | -------------------------------- |
| `ClaimDelegateSet` | Delegate address updated         |
| `Claimed`          | Successful token claim           |
| `Initialized`      | Successful aidrop initialization |

### Errors

| Error                       | Condition                                   |
| --------------------------- | ------------------------------------------- |
| `UnsupportedOperation`      | Operation not allowed                       |
| `TimeInactive`              | Outside airdrop claim window                |
| `InvalidSignature`          | Signature invalid                           |
| `LeafUsed`                  | Already claimed                             |
| `IncorrectFees`             | Fee amount mismatch                         |
| `OutsideClaimableTimeRange` | Outside claim window                        |
| `NotOwner`                  | Not airdrop owner                           |
| `NotProgramAdmin`           | Not program admin                           |
| `NotPermissioned`           | Missing permissions for user                |
| `InvalidFeeCollector`       | Provided fee collector account is incorrect |
| `Paused`                    | Airdrop is paused                           |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tokentable.xyz/for-developers/airdrop/solana/merkle-distributor.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
