> ## Documentation Index
> Fetch the complete documentation index at: https://docs.raydium.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Stable AMM accounts

> AmmInfo, ModelDataInfo, DataElement, Fees, and vault layout. The full account inventory of a Stable AMM pool (a standalone, pure-AMM Raydium program).

<Info>
  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.
</Info>

## Inventory

<Note>
  **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](/reference/changelog) 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.
</Note>

The active inventory is now entirely pool-side:

| Category | Account                              | Owner          | Role                                                                            |
| -------- | ------------------------------------ | -------------- | ------------------------------------------------------------------------------- |
| Pool     | `AmmInfo`                            | Stable program | Pool state, references to vaults and the model-data account.                    |
| Pool     | `amm_authority`                      | Stable program | Program-owned PDA that signs vault moves. Shared across all Stable AMM pools.   |
| Pool     | `amm_target_orders`                  | Stable program | Pool-side grid account (retained in layouts; no longer drives OpenBook orders). |
| Pool     | `pool_coin_token_account`            | SPL Token      | Pool's coin-side vault.                                                         |
| Pool     | `pool_pc_token_account`              | SPL Token      | Pool's pc-side vault.                                                           |
| Pool     | `lp_mint`                            | SPL Token      | Fungible LP mint.                                                               |
| Model    | **`model_data_account`**             | Stable program | **The lookup table: 50,000 × DataElement.**                                     |
| Legacy   | `amm_open_orders`                    | OpenBook       | The pool's old OpenBook `OpenOrders` account. **Unused.**                       |
| Legacy   | `serum_market`                       | OpenBook       | OpenBook market. **Unused.**                                                    |
| Legacy   | `serum_bids`, `serum_asks`           | OpenBook       | Bid/ask queues. **Unused.**                                                     |
| Legacy   | `serum_event_queue`                  | OpenBook       | Event queue. **Unused.**                                                        |
| Legacy   | `serum_coin_vault`, `serum_pc_vault` | SPL Token      | OpenBook market-level vaults. **Unused.**                                       |
| Legacy   | `serum_vault_signer`                 | OpenBook       | Market-level vault signer. **Unused.**                                          |

## `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.

```rust theme={null}
// raydium-stable/program/src/state.rs (abridged)
pub struct AmmInfo {
    pub account_type: u64,              // = 0 (AmmAccount)
    pub status: u64,                    // bitmask: swap/deposit/withdraw/crank enabled
    pub nonce: u64,                     // bump for amm_authority
    pub order_num: u64,
    pub depth: u64,
    pub coin_decimals: u64,
    pub pc_decimals: u64,
    pub state: u64,                     // state machine (IdleState, etc.)
    pub reset_flag: u64,
    pub min_size: u64,
    pub vol_max_cut_ratio: u64,
    pub amount_wave: u64,
    pub coin_lot_size: u64,             // mirrors OpenBook
    pub pc_lot_size: u64,
    pub min_price_multiplier: u64,
    pub max_price_multiplier: u64,
    pub sys_decimal_value: u64,
    pub abort_trade_factor: u64,
    pub price_tick_multiplier: u64,
    pub price_tick: u64,
    
    pub fees: Fees,                     // see below
    pub out_put: OutPutData,            // PnL, swaps, punish amounts
    
    pub coin_vault: Pubkey,
    pub pc_vault: Pubkey,
    pub coin_mint: Pubkey,
    pub pc_mint: Pubkey,
    pub lp_mint: Pubkey,
    pub model_data_key: Pubkey,         // ← THE LOOKUP TABLE
    pub open_orders: Pubkey,            // legacy: OpenBook OpenOrders (unused post-decoupling)
    pub serum_market: Pubkey,           // legacy: unused post-decoupling
    pub serum_program: Pubkey,          // legacy: unused post-decoupling
    pub target_orders: Pubkey,
    pub amm_admin: Pubkey,              // admin key
    pub client_order_id: u64,
    pub lp_amount: u64,                 // LP supply
    pub lp_net: u64,                    // LP value metric
    pub padding: [u64; 61],
}

pub struct Fees {
    pub min_separate_numerator: u64,
    pub min_separate_denominator: u64,
    pub trade_fee_numerator: u64,       // 25
    pub trade_fee_denominator: u64,     // 10_000 → 0.25%
    pub pnl_numerator: u64,             // 12
    pub pnl_denominator: u64,           // 100 → 12% of fee = 0.03% of volume
    pub swap_fee_numerator: u64,        // 25
    pub swap_fee_denominator: u64,      // 10_000
}

pub struct OutPutData {
    pub need_take_pnl_coin: u64,        // accrued protocol fee (coin)
    pub need_take_pnl_pc: u64,          // accrued protocol fee (pc)
    pub total_pnl_pc: u64,
    pub total_pnl_coin: u64,
    pub pool_open_time: u64,
    pub punish_pc_amount: u64,
    pub punish_coin_amount: u64,
    pub orderbook_to_init_time: u64,
    pub swap_coin_in_amount: u128,
    pub swap_pc_out_amount: u128,
    pub swap_pc_in_amount: u128,
    pub swap_coin_out_amount: u128,
    pub swap_pc_fee: u64,
    pub swap_coin_fee: u64,
}
```

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.

```rust theme={null}
// raydium-stable/program/src/state.rs
pub const ELEMENT_SIZE: usize = 50000;

pub struct DataElement {
    pub x: u64,         // table X (e.g., coin amount)
    pub y: u64,         // table Y (e.g., pc amount)
    pub price: u64,     // price at (x, y)
}

pub struct ModelDataInfo {
    pub account_type: u64,              // = 2 (ModleDataAccount)
    pub status: u64,                    // Initialized or Uninitialized
    pub multiplier: u64,                // scale factor for x, y (e.g., 10^6)
    pub valid_data_count: u64,          // how many elements are populated
    pub elements: [DataElement; 50000], // the table itself
}
```

**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.

```rust theme={null}
pub struct DataElement {
    pub x: u64,         // X coordinate (e.g., token_a balance, scaled by multiplier)
    pub y: u64,         // Y coordinate (e.g., token_b balance, scaled by multiplier)
    pub price: u64,     // price (x/y in scaled form, scaled by multiplier)
}
```

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:

```
Old: total assets = vault balances + open-order funds (native_coin_total / native_pc_total) − pending PnL (need_take_pnl)
New: total assets = vault balances − pending PnL (need_take_pnl)
```

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:

```
ammId = createWithSeed(
  owner: ammAuthority,
  seed: marketPubkey.toBase58().slice(0, 32),
  programId: STABLE_PROGRAM_ID,
)
```

Similarly for vaults, LP mint, target orders, etc. In practice, use the SDK or API to fetch pre-computed addresses.

## What to read where

* **Instruction account lists**: [`products/stable/instructions`](/products/stable/instructions).
* **How interpolation uses the table**: [`products/stable/math`](/products/stable/math).
* **Fee structure and WithdrawPnl**: [`products/stable/fees`](/products/stable/fees).
* **The 2026-06-22 OpenBook decoupling**: [`reference/changelog`](/reference/changelog).

Sources:

* [`reference/program-addresses`](/reference/program-addresses)
