Skip to main content
Stable AMM is its own program; its pool-side account structure resembles AMM v4 (AmmInfo, vaults, authority), and it additionally has a ModelDataInfo account that stores the lookup table. This page covers both.

Inventory

Pure AMM. Stable AMM holds all liquidity in its own vaults and does not depend on OpenBook. It carried an OpenBook market-making path early in its life, but that path has been dormant for years, and the 2026-06-22 upgrade removed the leftover code. The serum_* market accounts and amm_open_orders below are therefore legacy: they may still appear in old-layout transactions for backwards compatibility, but the program does not validate or read them, and new-layout instructions omit them entirely.
The active inventory is now entirely pool-side:

AmmInfo

Root state account. Layout is nearly identical to AMM v4 — pool params, decimals, fees, vault/mint references — with one addition: a model_data_key field pointing to the lookup table.
Key integrator-facing fields:
  • model_data_key — the address of the lookup table. Must be passed to every instruction.
  • fees — identical structure to AMM v4. Defaults to 0.25% trade fee, 0.22% LP / 0.03% protocol split.
  • coin_vault, pc_vault — the pools’ vaults.
  • status — bitmask gating swap/deposit/withdraw/crank.
  • out_put.need_take_pnl_* — swept by WithdrawPnl.

ModelDataInfo

The lookup table. A large sparse array of price/quantity points.
Lifecycle: The setup instructions that built these tables — InitModelData (created the account) and UpdateModelData (populated elements, setting valid_data_count) — were removed in the 2026-06-22 upgrade. The tables on existing pools are now fixed. At runtime, the remaining callable instructions still consume them:
  • Swap / deposit / withdraw call lookup functions that binary-search and interpolate within elements[0..valid_data_count].

DataElement

The atomic entry in the table. Must be sorted (x ascending, y descending, price ascending) for binary search to work.
When populating the table, the admin specifies these pre-scaled. The program does not validate sort order on-chain (for speed), so missorting causes incorrect quotes.

Authority and vaults

Same as AMM v4:
  • amm_authority is a single program-wide PDA derived with seed ["amm authority"]. It owns all pool vaults and signs their moves.
  • Vaults are SPL Token accounts whose owner is amm_authority, not ATAs.
Token-2022 is not supported.

Status bitmask

Identical to AMM v4. Controls whether swap/deposit/withdraw/crank are enabled.

Fee and PnL tracking

The out_put struct tracks:
  • need_take_pnl_coin, need_take_pnl_pc — protocol fees accrued but not yet swept. WithdrawPnl moves these out.
  • swap_coin_in_amount, swap_pc_in_amount, etc. — analytics counters.
Pool-asset calculation (post-decoupling). Because no funds are escrowed as OpenBook open orders anymore, the pool’s total assets are now computed entirely from the vaults:
Indexers and quoting code that reconstructed pool value from OpenOrders balances must drop that term.

Account size

The ModelDataInfo is large (~1.2 MB, since 50,000 elements × 24 bytes per element). This is why creating a Stable pool requires explicit rent and account pre-allocation. The Raydium SDK and tools handle this transparently; integrators rarely need to manually allocate.

Deriving accounts from scratch

Like AMM v4, Stable AMM uses seeded keys (not pure PDAs). The canonical pool identity is derived via:
Similarly for vaults, LP mint, target orders, etc. In practice, use the SDK or API to fetch pre-computed addresses.

What to read where

Sources: