Vote-Escrow Locking (veAXIO)
Lock AXIO tokens for governance power and revenue share with time-weighted multipliers and linear decay.
Vote-Escrow Locking (veAXIO)
Lock AXIO tokens to receive veAXIO -- a non-transferable governance token whose voting power and revenue share decay linearly over the lock period. Longer locks earn higher multipliers. Bootstrap participants receive enhanced rewards.
1. What is veAXIO?
veAXIO is a vote-escrow token minted on Token-2022 with the non-transferable extension. When you lock AXIO tokens into the ve-lock program, you receive veAXIO at a rate determined by your lock duration. veAXIO grants:
- Governance voting power -- proportional to your effective veAXIO balance
- Revenue share -- claim a share of MEV revenue distributed to the veAXIO staker pool
- Protocol influence -- fee parameter votes, emission schedule proposals
veAXIO is not transferable. It cannot be sold, sent, or used as collateral. It exists solely to represent your time-locked commitment to the protocol.
2. Lock Duration and Multipliers
The multiplier applied to your locked AXIO determines how much veAXIO you receive. Longer commitments earn higher multipliers.
Steady-State Multiplier Table
| Lock Duration | Multiplier | Slots | veAXIO per 1,000 AXIO |
|---|---|---|---|
| 1 month (min) | 1.0x | 6,480,000 | 1,000 |
| 3 months | 1.5x | 19,440,000 | 1,500 |
| 6 months | 2.0x | 38,880,000 | 2,000 |
| 12 months (max) | 4.0x | 77,760,000 | 4,000 |
Bootstrap Multiplier
During the bootstrap phase, the 12-month lock tier receives an enhanced 5.0x multiplier instead of the steady-state 4.0x. All other tiers remain unchanged.
| Lock Duration | Steady-State | Bootstrap |
|---|---|---|
| 1 month | 1.0x | 1.0x |
| 3 months | 1.5x | 1.5x |
| 6 months | 2.0x | 2.0x |
| 12 months | 4.0x | 5.0x |
Positions created during bootstrap retain their 5.0x multiplier for the full lock duration, even after bootstrap mode is deactivated. The is_bootstrap flag on each position records this permanently.
veAXIO Calculation
ve_amount = locked_amount * multiplier / 10000Multipliers are stored in basis points (10,000 = 1.0x). A 12-month bootstrap lock of 10,000 AXIO produces:
ve_amount = 10,000 * 50,000 / 10,000 = 50,000 veAXIO3. Linear Decay
veAXIO governance power decays linearly from lock creation to expiry. The effective balance at any point is:
effective_ve = ve_minted * remaining_slots / total_duration_slotsWhere:
remaining_slots = end_slot - current_slottotal_duration_slots = end_slot - start_slot
Decay Example
A user locks 1,000 AXIO for 12 months (4.0x multiplier), receiving 4,000 veAXIO:
| Time Elapsed | Remaining | Effective veAXIO | Governance Power |
|---|---|---|---|
| 0 months | 12 months | 4,000 | 100% |
| 3 months | 9 months | 3,000 | 75% |
| 6 months | 6 months | 2,000 | 50% |
| 9 months | 3 months | 1,000 | 25% |
| 12 months | 0 | 0 | 0% |
After the lock expires (current_slot >= end_slot), effective veAXIO returns 0. The user must withdraw to reclaim their AXIO and burn the veAXIO tokens.
4. Whale Cap
The whale cap prevents any single address from holding more than a configured percentage of the total veAXIO supply. The default is 500 bps (5%).
The check is performed on every Lock instruction:
user_new_ve_balance * 10,000 <= new_total_ve_supply * whale_cap_bpsIf the inequality is violated, the transaction fails with Whale cap exceeded. The admin can update the whale cap via the UpdateWhaleCap instruction (valid range: 1--10,000 bps).
5. PDA Derivation
All program accounts are derived as Program Derived Addresses (PDAs):
| Account | Seeds | Description |
|---|---|---|
| VeConfig | ["ve_config"] | Global configuration, one per deployment |
| LockPosition | ["lock", user_pubkey] | Per-user lock, one position per user |
| Vault | ["vault"] | PDA-owned ATA holding all locked AXIO |
// Derive VeConfig PDA
const [configPda] = PublicKey.findProgramAddressSync(
[Buffer.from("ve_config")],
VE_LOCK_PROGRAM_ID
);
// Derive LockPosition PDA for a user
const [positionPda] = PublicKey.findProgramAddressSync(
[Buffer.from("lock"), userPubkey.toBuffer()],
VE_LOCK_PROGRAM_ID
);6. Instructions
6.1 Initialize
Sets up the ve-lock program with default multiplier table and configuration. Admin only.
Parameters:
| Parameter | Type | Description |
|---|---|---|
whale_cap_bps | u16 | Maximum veAXIO share per address (bps) |
bootstrap_active | bool | Whether to start in bootstrap mode |
Accounts:
| # | Account | Signer | Writable | Description |
|---|---|---|---|---|
| 0 | Admin | Yes | No | Program admin authority |
| 1 | VeConfig PDA | No | Yes | Global config account (created) |
| 2 | AXIO Mint | No | No | Token-2022 AXIO mint |
| 3 | veAXIO Mint | No | Yes | Token-2022 veAXIO mint (created) |
| 4 | Vault | No | Yes | PDA-owned ATA for locked AXIO |
| 5 | Token-2022 Program | No | No | TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb |
| 6 | Associated Token Program | No | No | ATA program |
| 7 | System Program | No | No | System program |
| 8 | Rent Sysvar | No | No | Rent sysvar |
Default config on initialization:
min_lock_slots: 6,480,000 (1 month)max_lock_slots: 77,760,000 (12 months)- Multiplier table: 1.0x / 1.5x / 2.0x / 4.0x (5.0x bootstrap 12-month)
6.2 Lock
Lock AXIO tokens and receive veAXIO. Creates a new lock position for the user. Fails if a position already exists (use IncreaseLock or ExtendLock instead).
Parameters:
| Parameter | Type | Description |
|---|---|---|
amount | u64 | AXIO tokens to lock (must be > 0) |
duration_slots | u64 | Lock duration in slots (min 1 month, max 12 months) |
Accounts:
| # | Account | Signer | Writable | Description |
|---|---|---|---|---|
| 0 | User | Yes | No | Lock owner |
| 1 | VeConfig PDA | No | Yes | Global config |
| 2 | LockPosition PDA | No | Yes | User's position (created) |
| 3 | User AXIO Account | No | Yes | Source of AXIO tokens |
| 4 | Vault | No | Yes | Destination for locked AXIO |
| 5 | veAXIO Mint | No | Yes | Mint for veAXIO tokens |
| 6 | User veAXIO Account | No | Yes | Destination for minted veAXIO |
| 7 | Token-2022 Program | No | No | Token program |
| 8 | Associated Token Program | No | No | ATA program |
| 9 | System Program | No | No | System program |
| 10 | Clock Sysvar | No | No | For current slot |
6.3 IncreaseLock
Add more AXIO to an existing lock position. The additional veAXIO is minted at the position's original multiplier. The lock end slot does not change.
Parameters:
| Parameter | Type | Description |
|---|---|---|
additional_amount | u64 | Extra AXIO to add (must be > 0) |
Accounts: Same as Lock (position must already exist and not be expired).
6.4 ExtendLock
Extend the lock duration. If the extension crosses a multiplier tier boundary, additional veAXIO is minted to reflect the new multiplier.
Parameters:
| Parameter | Type | Description |
|---|---|---|
new_end_slot | u64 | New expiry slot (must be after current end slot) |
Accounts: Same as Lock (position must already exist).
The total duration (new_end_slot - start_slot) cannot exceed max_lock_slots (12 months). If the extension upgrades the multiplier tier (e.g., from 1.5x to 2.0x), the difference in veAXIO is minted automatically.
6.5 Withdraw
Withdraw all locked AXIO after the lock expires. Burns all veAXIO held by the user and returns the full locked amount.
Parameters: None.
Accounts:
| # | Account | Signer | Writable | Description |
|---|---|---|---|---|
| 0 | User | Yes | No | Position owner |
| 1 | VeConfig PDA | No | Yes | Global config |
| 2 | LockPosition PDA | No | Yes | User's position (cleared) |
| 3 | Vault | No | Yes | Source of locked AXIO |
| 4 | User AXIO Account | No | Yes | Destination for returned AXIO |
| 5 | veAXIO Mint | No | Yes | Mint (for burn) |
| 6 | User veAXIO Account | No | Yes | Source of veAXIO (burned) |
| 7 | Token-2022 Program | No | No | Token program |
| 8 | Clock Sysvar | No | No | For expiry check |
Fails if current_slot < end_slot (lock has not expired).
6.6 SetBootstrap
Toggle bootstrap mode on or off. Admin only.
Parameters:
| Parameter | Type | Description |
|---|---|---|
active | bool | Enable or disable bootstrap |
Accounts:
| # | Account | Signer | Writable | Description |
|---|---|---|---|---|
| 0 | Admin | Yes | No | Must match config admin |
| 1 | VeConfig PDA | No | Yes | Global config |
6.7 UpdateWhaleCap
Update the whale cap threshold. Admin only.
Parameters:
| Parameter | Type | Description |
|---|---|---|
whale_cap_bps | u16 | New cap (1--10,000 bps) |
Accounts:
| # | Account | Signer | Writable | Description |
|---|---|---|---|---|
| 0 | Admin | Yes | No | Must match config admin |
| 1 | VeConfig PDA | No | Yes | Global config |
7. Example: Full Lock Lifecycle
import { Connection, Keypair, PublicKey, Transaction } from "@solana/web3.js";
const connection = new Connection("https://rpc.x1.xyz");
const user = Keypair.fromSecretKey(/* ... */);
const PROGRAM_ID = new PublicKey("/* ve-lock program ID */");
// Step 1: Lock 5,000 AXIO for 6 months (~38,880,000 slots)
// At 2.0x multiplier, user receives 10,000 veAXIO
const lockIx = createLockInstruction({
user: user.publicKey,
amount: 5_000_000_000_000n, // 5,000 AXIO (9 decimals)
durationSlots: 38_880_000n,
programId: PROGRAM_ID,
});
// Step 2: After 2 months, add 2,000 more AXIO
// Minted at original 2.0x = 4,000 additional veAXIO
const increaseIx = createIncreaseLockInstruction({
user: user.publicKey,
additionalAmount: 2_000_000_000_000n,
programId: PROGRAM_ID,
});
// Step 3: Extend to 12 months total
// Multiplier upgrades from 2.0x to 4.0x
// Additional veAXIO minted for the difference
const extendIx = createExtendLockInstruction({
user: user.publicKey,
newEndSlot: startSlot + 77_760_000n,
programId: PROGRAM_ID,
});
// Step 4: After lock expires, withdraw everything
// All veAXIO burned, 7,000 AXIO returned
const withdrawIx = createWithdrawInstruction({
user: user.publicKey,
programId: PROGRAM_ID,
});8. State Account Layouts
VeConfig (189 bytes)
| Field | Type | Offset | Description |
|---|---|---|---|
is_initialized | bool | 0 | Initialization flag |
admin | Pubkey | 1 | Admin authority |
axio_mint | Pubkey | 33 | AXIO token mint |
ve_mint | Pubkey | 65 | veAXIO token mint |
vault | Pubkey | 97 | Locked AXIO vault |
min_lock_slots | u64 | 129 | Minimum lock duration |
max_lock_slots | u64 | 137 | Maximum lock duration |
multiplier_1mo | u64 | 145 | 1-month multiplier (bps) |
multiplier_3mo | u64 | 153 | 3-month multiplier (bps) |
multiplier_6mo | u64 | 161 | 6-month multiplier (bps) |
multiplier_12mo | u64 | 169 | 12-month multiplier (bps) |
bootstrap_multiplier_12mo | u64 | 177 | Bootstrap 12-month multiplier (bps) |
bootstrap_active | bool | 185 | Bootstrap mode flag |
whale_cap_bps | u16 | 186 | Whale cap in bps |
total_locked | u64 | 188 | Total AXIO locked |
bump | u8 | 196 | PDA bump seed |
LockPosition (75 bytes)
| Field | Type | Offset | Description |
|---|---|---|---|
is_initialized | bool | 0 | Initialization flag |
owner | Pubkey | 1 | Position owner |
locked_amount | u64 | 33 | AXIO tokens locked |
start_slot | u64 | 41 | Lock creation slot |
end_slot | u64 | 49 | Lock expiry slot |
multiplier | u64 | 57 | Applied multiplier (bps) |
ve_minted | u64 | 65 | veAXIO minted |
is_bootstrap | bool | 73 | Created during bootstrap |
bump | u8 | 74 | PDA bump seed |