Skip to main content
This page is the authoritative instruction reference. For code that actually composes these instructions, see products/cpmm/code-demos. For error-code meanings see reference/error-codes.

Instruction summary

Status bitmask: each pool’s status is a u8 where bit 0 = deposit disabled, bit 1 = withdraw disabled, bit 2 = swap disabled (PoolStatusBitIndex { Deposit, Withdraw, Swap } in the program). A clear bit means the operation is allowed; a set bit means it is paused. UpdatePoolStatus takes a raw u8 and overwrites the existing value. The next sections go through each in detail. Account ordering follows the CPMM IDL; the SDK and the Rust client in raydium-cp-swap/programs/cp-swap/src/instructions match this order.

Initialize

Create a new CPMM pool. Arguments
Accounts (W = writable, S = signer) * pool_state signs only on the random-keypair path; the canonical-PDA path runs without pool_state signing. Preconditions
  • Mints are sorted (token_0_mint < token_1_mint by byte order).
  • Neither mint uses an extension outside the CPMM allow-list (TransferFeeConfig, MetadataPointer, TokenMetadata, InterestBearingConfig, ScaledUiAmount) — see products/cpmm/accounts. A small per-mint allow-list inside the program bypasses the check for case-by-case onboarding.
  • creator has at least init_amount_0 and init_amount_1 in the respective ATAs.
  • amm_config.disable_create_pool == false.
Postconditions
  • pool_state exists with lp_supply = sqrt(init_amount_0 * init_amount_1) − LOCKED_LP.
  • The LP starter of LOCKED_LP (100 lamports of LP token) is permanently locked in the pool — pool_state.lp_supply records liquidity − 100 while 100 LP units remain outside circulation, preventing the pool from being fully drained and dividing by zero.
  • observation_state is initialized; observation_index = 0 and pool_id = pool_state.key().
  • create_pool_fee lamports are transferred from the creator to the receiver and synced as native SOL (it is a wSOL ATA).
  • The pool’s status bitmask is 0 (deposit / withdraw / swap all enabled).
  • enable_creator_fee = false and creator_fee_on = BothToken. Initialize does not support enabling the creator fee — that path is InitializeWithPermission.
  • open_time is bumped to block_timestamp + 1 if the caller passed a value <= block_timestamp. Swaps are rejected before open_time; deposits and withdrawals work immediately.
Common errors (full list in reference/error-codes)
  • InvalidInput — mints unsorted, or identical mints.
  • NotSupportMint — blocked Token-2022 extension.
  • ExceededSlippage — rarely; if init_amount_0/1 result in zero LP due to decimals mismatch.

Deposit

Add liquidity in both tokens proportional to the pool. Arguments
Accounts Math
No change to k’s proportionality — both vaults and lp_supply scale by the same factor. Postconditions
  • lp_supply += lp_token_amount.
  • vault_0 += needed_token_0 (net of any Token-2022 transfer fee on input).
  • vault_1 += needed_token_1 (net of any Token-2022 transfer fee on input).
Common errorsExceededSlippage, ZeroTradingTokens, InvalidStatus if deposit is paused.

Withdraw

Burn LP tokens and receive both underlying tokens pro-rata. Arguments
Accounts (Identical to Deposit; lp_mint is writable because the LP tokens are burned.) Math
Postconditions
  • lp_supply -= lp_token_amount.
  • Vaults send out_token_0 / out_token_1 (gross; the user receives net of any Token-2022 transfer fee).

SwapBaseInput

Exact-input swap. Arguments
Accounts The ordering input → output is by the user’s direction, not by the pool’s canonical token_0 / token_1. The program figures out which vault is which by matching mints. Math — see products/cpmm/math. Preconditions
  • open_time <= now.
  • pool_status allows swap.
  • Neither mint paused or frozen for this authority.
  • amount_in > 0.
Common errors
  • ExceededSlippageamount_out < minimum_amount_out.
  • ZeroTradingTokens — the trade rounds to zero.
  • NotApproved — pool is paused for swaps via UpdatePoolStatus.
  • InvalidInput — mints do not match either of the pool’s vault mints.

SwapBaseOutput

Exact-output swap. Arguments
Accounts — same as SwapBaseInput. Math — inverse curve with ceiling, see products/cpmm/math. Common errorsExceededSlippage (gross_in > max_amount_in), ZeroTradingTokens, InvalidInput, NotApproved.

CollectProtocolFee

Sweep accrued protocol fees from the vaults to the protocol destination. Arguments — none. Accounts Effect
No change to the curve’s effective balances (accrued fees were already excluded). Common errorNotApproved if signer is not protocol_owner.

CollectFundFee

Same shape as CollectProtocolFee but signed by fund_owner and zeroing the fund_fees_* counters.

CollectCreatorFee

Same shape again, signed by pool_state.pool_creator. Only emits transfers if the pool was initialized with a non-zero creator-fee rate.

UpdatePoolStatus

Pause or resume individual operations on a pool. The status field is a bitmask: Arguments
Accounts The admin key is the upgrade authority on the CPMM program — in practice, the Raydium multisig. See security/admin-and-multisig.

CreateAmmConfig

Create a new fee tier. Arguments
Accounts Preconditions
  • No existing AmmConfig with the same index.
  • protocol_fee_rate + fund_fee_rate <= FEE_RATE_DENOMINATOR_VALUE.

UpdateAmmConfig

Change fee rates or ownership on an existing AmmConfig. Takes a param: u8 (discriminator for which field to update) and a value: u64. The value semantics per param are in the source; commonly:
  • param = 0trade_fee_rate
  • param = 1protocol_fee_rate
  • param = 2fund_fee_rate
  • param = 3new_protocol_owner (pass Pubkey bytes as a reinterpret)
  • param = 4new_fund_owner
  • param = 5create_pool_fee
  • param = 6disable_create_pool
Changes are signed by the admin and affect every pool bound to this AmmConfig on the next swap. No migration; pools simply read the new values.

State-change matrix

Where to go next

Sources: