FortiBlox LogoFortiBlox Docs
AXIO Block Engine

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 DurationMultiplierSlotsveAXIO per 1,000 AXIO
1 month (min)1.0x6,480,0001,000
3 months1.5x19,440,0001,500
6 months2.0x38,880,0002,000
12 months (max)4.0x77,760,0004,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 DurationSteady-StateBootstrap
1 month1.0x1.0x
3 months1.5x1.5x
6 months2.0x2.0x
12 months4.0x5.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 / 10000

Multipliers 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 veAXIO

3. 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_slots

Where:

  • remaining_slots = end_slot - current_slot
  • total_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 ElapsedRemainingEffective veAXIOGovernance Power
0 months12 months4,000100%
3 months9 months3,00075%
6 months6 months2,00050%
9 months3 months1,00025%
12 months000%

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_bps

If 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):

AccountSeedsDescription
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:

ParameterTypeDescription
whale_cap_bpsu16Maximum veAXIO share per address (bps)
bootstrap_activeboolWhether to start in bootstrap mode

Accounts:

#AccountSignerWritableDescription
0AdminYesNoProgram admin authority
1VeConfig PDANoYesGlobal config account (created)
2AXIO MintNoNoToken-2022 AXIO mint
3veAXIO MintNoYesToken-2022 veAXIO mint (created)
4VaultNoYesPDA-owned ATA for locked AXIO
5Token-2022 ProgramNoNoTokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
6Associated Token ProgramNoNoATA program
7System ProgramNoNoSystem program
8Rent SysvarNoNoRent 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:

ParameterTypeDescription
amountu64AXIO tokens to lock (must be > 0)
duration_slotsu64Lock duration in slots (min 1 month, max 12 months)

Accounts:

#AccountSignerWritableDescription
0UserYesNoLock owner
1VeConfig PDANoYesGlobal config
2LockPosition PDANoYesUser's position (created)
3User AXIO AccountNoYesSource of AXIO tokens
4VaultNoYesDestination for locked AXIO
5veAXIO MintNoYesMint for veAXIO tokens
6User veAXIO AccountNoYesDestination for minted veAXIO
7Token-2022 ProgramNoNoToken program
8Associated Token ProgramNoNoATA program
9System ProgramNoNoSystem program
10Clock SysvarNoNoFor 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:

ParameterTypeDescription
additional_amountu64Extra 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:

ParameterTypeDescription
new_end_slotu64New 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:

#AccountSignerWritableDescription
0UserYesNoPosition owner
1VeConfig PDANoYesGlobal config
2LockPosition PDANoYesUser's position (cleared)
3VaultNoYesSource of locked AXIO
4User AXIO AccountNoYesDestination for returned AXIO
5veAXIO MintNoYesMint (for burn)
6User veAXIO AccountNoYesSource of veAXIO (burned)
7Token-2022 ProgramNoNoToken program
8Clock SysvarNoNoFor expiry check

Fails if current_slot < end_slot (lock has not expired).

6.6 SetBootstrap

Toggle bootstrap mode on or off. Admin only.

Parameters:

ParameterTypeDescription
activeboolEnable or disable bootstrap

Accounts:

#AccountSignerWritableDescription
0AdminYesNoMust match config admin
1VeConfig PDANoYesGlobal config

6.7 UpdateWhaleCap

Update the whale cap threshold. Admin only.

Parameters:

ParameterTypeDescription
whale_cap_bpsu16New cap (1--10,000 bps)

Accounts:

#AccountSignerWritableDescription
0AdminYesNoMust match config admin
1VeConfig PDANoYesGlobal 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)

FieldTypeOffsetDescription
is_initializedbool0Initialization flag
adminPubkey1Admin authority
axio_mintPubkey33AXIO token mint
ve_mintPubkey65veAXIO token mint
vaultPubkey97Locked AXIO vault
min_lock_slotsu64129Minimum lock duration
max_lock_slotsu64137Maximum lock duration
multiplier_1mou641451-month multiplier (bps)
multiplier_3mou641533-month multiplier (bps)
multiplier_6mou641616-month multiplier (bps)
multiplier_12mou6416912-month multiplier (bps)
bootstrap_multiplier_12mou64177Bootstrap 12-month multiplier (bps)
bootstrap_activebool185Bootstrap mode flag
whale_cap_bpsu16186Whale cap in bps
total_lockedu64188Total AXIO locked
bumpu8196PDA bump seed

LockPosition (75 bytes)

FieldTypeOffsetDescription
is_initializedbool0Initialization flag
ownerPubkey1Position owner
locked_amountu6433AXIO tokens locked
start_slotu6441Lock creation slot
end_slotu6449Lock expiry slot
multiplieru6457Applied multiplier (bps)
ve_mintedu6465veAXIO minted
is_bootstrapbool73Created during bootstrap
bumpu874PDA bump seed

Next Steps