# 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="https://2778259896-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPwpN13H2gt6vlHSZcOAi%2Fuploads%2FAi29LrvdNzCzdpUBcIzX%2FUntitled%20diagram%20_%20Mermaid%20Chart-2025-07-08-190045.png?alt=media&#x26;token=4b5702ee-52f5-41ab-b94f-250629ca09da" 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                           |
