# Solana

### Introduction

TokenTable Unlocker provides users with a secure, self-custodial token management and unlocking experience. Once initialized, Unlocker is fully independent from us, with each token unlock managed solely by the project owner.

## 🚀 Quick Start

### What is TokenTable Unlocker?

TokenTable Unlocker is our most independent and feature-rich token distributor. Targeted specifically for fine-tuned and complex token unlocking onchain, Unlocker sets itself apart with the following features: customizable unlocking schedules, partial deposits, unruggable configurations, delegate claiming, streamlined gas efficiency, and a comprehensive dashboard to help build the ideal unlocking schedule. Unlocker splits token distributions into presets, which outline an unlocking schedule for a group of recipients, and actuals, which define necessary claim-related variables, such as the amount of tokens a recipient is allocated.

### Key Benefits

* ✅ **Fully Independent** - Initialized unlockers are independently managed by project owners
* ✅ **Customizable Unlocking Schedules** - Linear unlocks, cliff unlocks, and flexible pauses
* ✅ **Partial Deposits** - A full deposit is not required upfront
* ✅ **Unruggable Standard** - Token unlocks can be configured for no-cancel and no-withdrawal restrictions
* ✅ **Claiming Tokens on Behalf of Recipients** - Delegate users can send unlocked tokens directly to recipients' wallets
* ✅ **Comprehensive Dashboard** - Easily create, view, and track all relevant unlocker information from a personalized dashboard

## 📋 System Overview

### Account Structure

<figure><img src="https://2778259896-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPwpN13H2gt6vlHSZcOAi%2Fuploads%2FDb9dVG2lJqb36peUQU2H%2FUntitled%20diagram%20_%20Mermaid%20Chart-2025-07-10-012547.png?alt=media&#x26;token=e07323fc-b2b2-4a92-8117-51de92a2d478" 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,
}
```

The TokenTable Unlocker program can manage multiple token unlocks. Each initialized unlocker uses the following storage pattern:

```rust
pub struct Unlocker {
  pub owner: Pubkey,
  pub project_token: Pubkey,
  pub fee_collector: Pubkey,
  pub fee_token: Pubkey,
  pub is_createable: bool,
  pub is_cancelable: bool,
  pub is_transferable: bool,
  pub is_withdrawable: bool,
  #[max_len(20)]
  pub project_id: String,
}
```

### 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,
  actual_id: u64,
  batch_id: u64
 ) -> Result<()>
```

### **Security Features**

* Reentrancy protection on all claim functions
* Time-based token allocation calculations
* 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                             |
| Unlocker Owner | Set unlocker parameters, withdraw tokens, transfer unlocker ownership |
| Delegate       | Claim on behalf of recipients                                         |
| Users          | Claim their allocated tokens                                          |

### Security Features

* **Reentrancy Guards** - All state-changing functions protected
* **Time Windows** - Enforced distribution periods

## 📡 Events & Errors

### Events

| Event                    | Description                                          |
| ------------------------ | ---------------------------------------------------- |
| `Initialized`            | Successful unlocker initialization                   |
| `ActualCreated`          | Successful actual creation                           |
| `PresetCreated`          | Successful preset creation                           |
| `ClaimingDelegateSet`    | Delegate account permissions changed                 |
| `TokensClaimed`          | Tokens claimed successfully                          |
| `ActualCancelled`        | Successfully cancelled an actual                     |
| `TokensWithdrawn`        | Successfully withdrew tokens                         |
| `CreateDisabled`         | Successfully disabled creating actuals               |
| `CancelDisabled`         | Successfully disabled cancel functionality           |
| `TransferActualDisabled` | Successfully disabled actual transfer functionality  |
| `WithdrawDisabled`       | Successfully disabled token withdrawal functionality |

### Errors

| Error                 | Description                                                                |
| --------------------- | -------------------------------------------------------------------------- |
| `ActualDoesNotExist`  | Actual does not exist                                                      |
| `PresetDoesNotExist`  | Actual does not reference a valid preset                                   |
| `DataMismatch`        | Call parameters do not match supplied accounts in transaction              |
| `InvalidPresetFormat` | Preset data contains inconsistencies or an invalid ID                      |
| `InvalidSkipAmount`   | An actual's `amount_claimed` must be less than the actual's `total_amount` |
| `NotOwner`            | Not unlocker owner                                                         |
| `NotProgramAdmin`     | Not program admin                                                          |
| `NotTransferable`     | Unlocker does not allow the transfer of actuals                            |
| `NotWithdrawable`     | Unlocker does not allow the withdrawal of deposited tokens                 |
| `NotPermissioned`     | Missing permissions for user or unlocker feature disabled                  |
| `InvalidFeeCollector` | Provided fee collector account is incorrect                                |
