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

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.
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:
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:
Direct Claim - Recipients claim their own tokens
Delegate Claim - Authorized delegate claims for recipients
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
Fee Collector - External
FeeCollector
program that calculates and manages vault accountsFee Token - Native or SPL token for fees
Vault Accounts - Program Derived Accounts (PDAs) for holding fee tokens
🔒 Security
Access Control
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
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
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
Last updated
Was this helpful?