State transitions

Think of a pool lifecycle as a sequence of explicit transitions. Here is the “happy path” plus control paths.

Pool creation

A. init_pool

Creates:

  • pool PDA (state)

  • lp_mint

  • registry PDA

Inputs:

  • base_mint, quote_mint

  • bin_step_bps

  • initial_price_q64_64

  • fee_config (FeeConfig struct)

Emits:

  • PoolInitialised

B. init_pool_vaults

Creates and attaches the SPL token accounts:

  • base_vault, quote_vault

  • creator_fee_vault, holders_fee_vault, nft_fee_vault

After this step, the pool has somewhere to hold liquidity and fees.

Bin provisioning

create_liquidity_bin

Creates a bin PDA at a specific index with bounds and optional analytics liquidity.

Emits:

  • LiquidityBinCreated

This is typically done by admin (or a pool operator workflow) so the pool has a known bin lattice.

User deposits and LP shares

deposit_into_bins

  • Depositor provides base and/or quote into chosen bin indices.

  • Funds move from depositor_base/depositor_quote into base_vault/quote_vault.

  • LP shares are minted to depositor_lp.

Emits:

  • LiquidityDeposited

  • And bin updates via BinLiquidityUpdated

Conceptually:

Swaps

swap

  • User pays amount_in from user_source.

  • Pool routes through bins (via SwapRoute.bin_indices).

  • User receives output to user_destination.

  • Fees are split during the swap into:

    • creator_fee_vault

    • holders_fee_vault

    • nft_fee_vault

  • Reserves update per bin traversal.

Emits:

  • SwapExecuted

  • FeesDistributed

  • BinLiquidityUpdated

Slippage safety:

  • min_amount_out enforced

  • Error SlippageExceeded if protection fails.

Withdrawals

User withdrawal: withdraw_user

  • Burns LP shares from user_lp.

  • Returns pro-rata base/quote from pool vaults to user_base and user_quote.

  • Enforces lock rules if liquidity_lock exists and is still active.

Emits:

  • LiquidityWithdrawnUser

Admin-only withdrawal: withdraw_liquidity

  • Burns shares from admin_lp and moves assets to admin_base/admin_quote.

  • This is labeled “legacy/admin-only withdrawal” in the IDL and should be tightly governed, especially for permissioned pools.

Emits:

  • LiquidityWithdrawnAdmin

Liquidity locking

lock_liquidity

  • Moves LP tokens from user_lp into escrow_lp (owned by pool PDA).

  • Writes lock metadata to liquidity_lock PDA (amount + lock_end).

Emits:

  • LiquidityLocked

This creates a hard on-chain rule: locked LP cannot be withdrawn until the lock expires (error 6034).

Fee claiming and distribution

claim_protocol_fees

  • Withdraws from fee vaults into destination accounts:

    • creator_fee_vault -> creator_destination

    • holders_fee_vault -> holders_destination

    • nft_fee_vault -> nft_destination

Arguments are explicit amounts:

This design is intentionally simple: the program holds fees in vaults and a designated authority triggers withdrawals to downstream distributors (creator treasury, holder rewards distributor, NFT rewards distributor).

Governance and safety controls

Admin rotation

  • update_admin changes pool.admin

  • Emits AdminUpdated

Authorities

  • update_authorities updates:

    • config_authority

    • pause_guardian

    • fee_withdraw_authority

  • Emits AuthoritiesUpdated

Fee config updates

  • update_fee_config updates the fee configuration fields

  • Emits FeeConfigUpdated

Pausing

  • set_pause toggles pool paused state

  • set_pause_bits sets a bitmask (guardian-only) for granular disabling (swap/deposit/withdraw)

Last updated