Passer au contenu principal
Cette page est traduite automatiquement par IA. La version anglaise fait foi.Voir la version anglaise →
Stable AMM est son propre programme ; sa structure de comptes côté pool ressemble à AMM v4 (AmmInfo, vaults, autorité), et elle dispose en outre d’un compte ModelDataInfo qui stocke la table de recherche. Cette page couvre les deux.

Inventaire

AMM pur. Stable AMM détient toute la liquidité dans ses propres vaults et ne dépend pas d’OpenBook. Il a porté un chemin de tenue de marché OpenBook au début de sa vie, mais ce chemin est dormant depuis des années, et la mise à jour du 2026-06-22 a supprimé le code restant. Les comptes de marché serum_* et amm_open_orders ci-dessous sont donc hérités : ils peuvent encore apparaître dans les anciennes transactions de disposition pour la compatibilité rétroactive, mais le programme ne les valide ni ne les lit, et les nouvelles instructions les omettent entièrement.
L’inventaire actif est maintenant entièrement côté pool :
CatégorieComptePropriétaireRôle
PoolAmmInfoProgramme StableÉtat du pool, références aux vaults et au compte de données du modèle.
Poolamm_authorityProgramme StablePDA détenu par le programme qui signe les mouvements de vault. Partagé entre tous les pools Stable AMM.
Poolamm_target_ordersProgramme StableCompte de grille côté pool (conservé dans les dispositions ; ne pilote plus les ordres OpenBook).
Poolpool_coin_token_accountSPL TokenVault côté coin du pool.
Poolpool_pc_token_accountSPL TokenVault côté pc du pool.
Poollp_mintSPL TokenMint LP fongible.
Modèlemodel_data_accountProgramme StableLa table de recherche : 50 000 × DataElement.
Héritéamm_open_ordersOpenBookL’ancien compte OpenOrders OpenBook du pool. Inutilisé.
Héritéserum_marketOpenBookMarché OpenBook. Inutilisé.
Héritéserum_bids, serum_asksOpenBookFiles d’attente des offres/demandes. Inutilisées.
Héritéserum_event_queueOpenBookFile d’attente des événements. Inutilisée.
Héritéserum_coin_vault, serum_pc_vaultSPL TokenVaults au niveau du marché OpenBook. Inutilisés.
Héritéserum_vault_signerOpenBookSignataire de vault au niveau du marché. Inutilisé.

AmmInfo

Compte d’état racine. La disposition est presque identique à AMM v4 — paramètres du pool, décimales, frais, références aux vaults/mints — avec un ajout : un champ model_data_key pointant vers la table de recherche.
// 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,
}
Champs clés côté intégrateur :
  • model_data_key — l’adresse de la table de recherche. Doit être passée à chaque instruction.
  • fees — structure identique à AMM v4. Par défaut, frais de swap de 0,25 %, répartition LP / protocole de 0,22 % / 0,03 %.
  • coin_vault, pc_vault — les vaults des pools.
  • status — bitmask contrôlant le swap/dépôt/retrait/crank.
  • out_put.need_take_pnl_* — balayés par WithdrawPnl.

ModelDataInfo

La table de recherche. Un grand tableau creux de points prix/quantité.
// 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
}
Cycle de vie : Les instructions de configuration qui ont construit ces tables — InitModelData (créé le compte) et UpdateModelData (éléments peuplés, définissant valid_data_count) — ont été supprimées dans la mise à jour du 2026-06-22. Les tables sur les pools existants sont maintenant fixes. À l’exécution, les instructions appelables restantes les consomment toujours :
  • Swap / dépôt / retrait appellent des fonctions de recherche qui font une recherche binaire et interpolent dans elements[0..valid_data_count].

DataElement

L’entrée atomique dans la table. Doit être triée (x croissant, y décroissant, prix croissant) pour que la recherche binaire fonctionne.
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)
}
Lors du remplissage de la table, l’administrateur spécifie ces pré-mises à l’échelle. Le programme ne valide pas l’ordre de tri en chaîne (pour la vitesse), donc un tri incorrect provoque des devis incorrects.

Autorité et vaults

Identique à AMM v4 :
  • amm_authority est un PDA unique au niveau du programme dérivé avec la graine ["amm authority"]. Il possède tous les vaults du pool et signe leurs mouvements.
  • Les vaults sont des comptes SPL Token dont le propriétaire est amm_authority, pas des ATA.
Token-2022 n’est pas supporté.

Bitmask de statut

Identique à AMM v4. Contrôle si le swap/dépôt/retrait/crank sont activés.

Suivi des frais et du PnL

La structure out_put suit :
  • need_take_pnl_coin, need_take_pnl_pc — frais de protocole accumulés mais pas encore balayés. WithdrawPnl les déplace.
  • swap_coin_in_amount, swap_pc_in_amount, etc. — compteurs d’analyse.
Calcul des actifs du pool (post-découplage). Parce qu’aucun fonds n’est plus bloqué en tant que commandes ouvertes OpenBook, les actifs totaux du pool sont maintenant calculés entièrement à partir des vaults :
Ancien : actifs totaux = soldes des vaults + fonds des ordres ouverts (native_coin_total / native_pc_total) − PnL en attente (need_take_pnl)
Nouveau : actifs totaux = soldes des vaults − PnL en attente (need_take_pnl)
Les indexeurs et le code de cotation qui ont reconstruit la valeur du pool à partir des soldes OpenOrders doivent supprimer ce terme.

Taille du compte

Le ModelDataInfo est volumineux (~1,2 Mo, puisque 50 000 éléments × 24 octets par élément). C’est pourquoi la création d’un pool Stable nécessite une pré-allocation explicite de loyer et de compte. Le SDK Raydium et les outils gèrent cela de manière transparente ; les intégrateurs ont rarement besoin d’allouer manuellement.

Dérivation des comptes à partir de zéro

Comme AMM v4, Stable AMM utilise des clés avec graine (pas des PDA purs). L’identité canonique du pool est dérivée via :
ammId = createWithSeed(
  owner: ammAuthority,
  seed: marketPubkey.toBase58().slice(0, 32),
  programId: STABLE_PROGRAM_ID,
)
De même pour les vaults, le mint LP, les ordres cibles, etc. En pratique, utilisez le SDK ou l’API pour récupérer les adresses pré-calculées.

Où lire quoi

Sources :