Skip to main content
Cette page est traduite automatiquement par IA. La version anglaise fait foi.Voir la version anglaise →
Cette page est la référence d’instruction faisant autorité. Pour le code qui compose réellement ces instructions, consultez products/cpmm/code-demos. Pour les significations des codes d’erreur, consultez reference/error-codes.La mise à niveau du programme 2026-09 a reconstruit CPMM sur Anchor 1.0.2 / Solana 3.1.10, a ajouté l’instruction admin CollectExcessLamports, a supprimé la liste blanche de mints Token-2022 codée en dur, et a modifié ce que CreateAmmConfig écrit dans protocol_owner / fund_owner. Aucune instruction orientée utilisateur n’a changé ses comptes, arguments ou mathématiques. Consultez l’entrée du journal des modifications du 2026-09-09.
Les deux instructions de collecte de frais créateurs ont changé leurs listes de comptes le 2026-09-19. CollectCreatorFee gagne creator_fee_share ; CollectCreatorFeePermissionless gagne amm_config et creator_fee_share. Les deux sont ajoutés après system_program, donc chaque compte qu’un client existant passe déjà conserve son index — mais les nouveaux comptes sont obligatoires, donc une transaction construite selon l’ancienne disposition se retrouve à court de comptes et est rejetée avec l’erreur AccountNotEnoughKeys (3005) d’Anchor. Deux instructions admin — CreateCreatorFeeShare et CloseCreatorFeeShare — sont ajoutées, et UpdateAmmConfig prend un nouveau param = 8. Consultez l’entrée du journal des modifications du 2026-09-19.

Résumé des instructions

Masque de statut : le status de chaque pool est un u8 où le bit 0 = dépôt désactivé, bit 1 = retrait désactivé, bit 2 = swap désactivé (PoolStatusBitIndex { Deposit, Withdraw, Swap } dans le programme). Un bit clair signifie que l’opération est autorisée ; un bit défini signifie qu’elle est en pause. UpdatePoolStatus prend un u8 brut et remplace la valeur existante. Les sections suivantes détaillent chacune. L’ordre des comptes suit l’IDL CPMM ; le SDK et le client Rust dans raydium-cp-swap/programs/cp-swap/src/instructions correspondent à cet ordre.

Initialize

Créer un nouveau pool CPMM. Arguments
Comptes (W = inscriptible, S = signataire) * pool_state signe uniquement sur le chemin de paire aléatoire ; le chemin PDA canonique s’exécute sans que pool_state signe. Conditions préalables
  • Les mints sont triés (token_0_mint < token_1_mint par ordre d’octets).
  • Aucun mint n’utilise une extension en dehors de la liste blanche CPMM (TransferFeeConfig, MetadataPointer, TokenMetadata, InterestBearingConfig, ScaledUiAmount) — voir products/cpmm/accounts. Un mint dont le PDA SupportMintAssociated (seed [b"support_mint", mint]) existe ignore la vérification d’extension — mais vous devez ajouter ce PDA à remaining_accounts. Le programme ne scanne que les comptes que vous passez et ne charge jamais le PDA lui-même, donc compter sur le registre sans fournir le compte échoue quand même avec NotSupportMint (6007). L’ordre n’a pas d’importance (la correspondance se fait par clé) ; passez une entrée par mint qui a besoin du contournement. Ce registre est le seul contournement depuis que la mise à niveau 2026-09 a supprimé la liste blanche de quatre mints codée en dur.
  • creator a au moins init_amount_0 et init_amount_1 dans les ATAs respectifs.
  • amm_config.disable_create_pool == false.
Postconditions
  • pool_state.lp_supply = sqrt(init_amount_0 * init_amount_1) — la racine carrée complète. Le créateur reçoit lp_supply − 100 ; les 100 unités de base verrouillées sont comptées dans lp_supply mais jamais créées.
  • Donc lp_mint.supply == pool_state.lp_supply − 100 pour la durée de vie du pool. Toutes les mathématiques de part LP (dépôt, retrait) divisent par lp_supply, donc utilisez ce champ et ne substituez pas l’approvisionnement du mint en chaîne. Revient avec InitLpAmountTooLess si sqrt(...) < 100.
  • observation_state est initialisé ; observation_index = 0 et pool_id = pool_state.key().
  • Les lamports create_pool_fee sont transférés du créateur au destinataire et synchronisés en SOL natif (c’est un ATA wSOL).
  • Le masque de statut du pool est 0 (dépôt / retrait / swap tous activés).
  • enable_creator_fee = false et creator_fee_on = BothToken. Initialize ne supporte pas l’activation des frais créateurs — ce chemin est InitializeWithPermission.
  • open_time est augmenté à block_timestamp + 1 si l’appelant a passé une valeur <= block_timestamp. Les swaps sont rejetés avant open_time ; les dépôts et retraits fonctionnent immédiatement.
Erreurs courantes (liste complète dans reference/error-codes)
  • InvalidInput — mints non triés, ou mints identiques.
  • NotSupportMint — extension Token-2022 bloquée.
  • ExceededSlippage — rarement ; si init_amount_0/1 résultent en zéro LP en raison d’une inadéquation de décimales.

Deposit

Ajouter de la liquidité dans les deux tokens proportionnellement au pool. Arguments
Comptes Mathématiques
Deux détails à épingler : la base au prorata est le total du vault excluant les frais (vault_amount_without_fee, c’est-à-dire le solde brut moins les compteurs de frais de protocole, de fonds et de créateurs accumulés), pas le solde brut du vault ; et le plafond de slippage est vérifié par rapport à ce que le payeur transfère réellement, après que le frais de transfert Token-2022 soit ajouté, pas par rapport au mouvement brut du vault. Aucun changement à la proportionnalité de k — les deux totaux et lp_supply se mettent à l’échelle par le même facteur. Postconditions
  • lp_supply += lp_token_amount.
  • vault_0 += needed_token_0 (net de tout frais de transfert Token-2022 sur l’entrée).
  • vault_1 += needed_token_1 (net de tout frais de transfert Token-2022 sur l’entrée).
Erreurs courantes — ExceededSlippage, ZeroTradingTokens, InvalidStatus si le dépôt est en pause.

Withdraw

Brûler les tokens LP et recevoir les deux tokens sous-jacents au prorata. Arguments
Comptes Les 13 premiers comptes sont identiques à Deposit, et lp_mint est inscriptible car les tokens LP sont brûlés. Withdraw prend en plus un 14e compte, memo_program (contraint address = memo::ID) — Deposit ne le fait pas. Un Withdraw à 13 comptes échoue la désérialisation Anchor, donc le LP ne peut pas sortir. Mathématiques
Postconditions
  • lp_supply -= lp_token_amount.
  • Les vaults envoient out_token_0 / out_token_1 (brut ; l’utilisateur reçoit net de tout frais de transfert Token-2022).

SwapBaseInput

Swap à entrée exacte. Arguments
Comptes L’ordre entrée → sortie est par la direction de l’utilisateur, pas par le token_0 / token_1 canonique du pool. Le programme détermine quel vault est lequel en faisant correspondre les mints. Mathématiques — voir products/cpmm/math. Conditions préalables
  • open_time <= now.
  • pool_status autorise le swap.
  • Aucun mint en pause ou gelé pour cette autorité.
  • amount_in > 0.
Erreurs courantes
  • ExceededSlippage — amount_out < minimum_amount_out.
  • ZeroTradingTokens — le commerce s’arrondit à zéro.
  • NotApproved — le pool est en pause pour les swaps via UpdatePoolStatus.
  • InvalidInput — les mints ne correspondent à aucun des mints du vault du pool.

SwapBaseOutput

Swap à sortie exacte. Arguments
Comptes — identiques à SwapBaseInput. Mathématiques — courbe inverse avec plafond, voir products/cpmm/math. Erreurs courantes — ExceededSlippage (gross_in > max_amount_in), ZeroTradingTokens, InvalidInput, NotApproved.

CollectProtocolFee

Collecter les frais de protocole accumulés des vaults vers la destination du protocole. Arguments — aucun. Comptes Effet
Aucun changement aux soldes effectifs de la courbe (les frais accumulés étaient déjà exclus). Erreur courante — InvalidOwner (6001) si le signataire n’est ni amm_config.protocol_owner ni l’admin du programme. (Il n’y a pas de NotApproved sur ce chemin.)

CollectFundFee

Même forme que CollectProtocolFee mais signé par amm_config.fund_owner — ou, encore une fois, l’admin du programme — et mettant à zéro les compteurs fund_fees_*. Même InvalidOwner sur un mauvais signataire.

CollectCreatorFee

Signé par pool_state.pool_creator. Il règle les frais créateurs accumulés et transfère la part du créateur vers les comptes de tokens du créateur. Arguments — aucun. Comptes Effet
La part du protocole ne quitte jamais le vault ici — elle est réétiquetée comme un frais de protocole et attend CollectProtocolFee. Les deux compteurs sont déjà exclus de la vue du pool de la vault, donc le prix du pool ne bouge pas. Dérivation complète dans products/cpmm/fees. Erreurs courantes — NoFeeCollect quand les deux compteurs de créateurs sont zéro (vérifiés avant la division), InvalidInput (6003) si le share_rate résolu dépasse 1_000_000, MathOverflow (6011) si l’enregistrement de la part déborderait protocol_fees_token_*, et l’erreur ConstraintSeeds d’Anchor si creator_fee_share n’est pas le PDA canonique.

CollectCreatorFeePermissionless

N’importe qui peut déclencher la collecte des frais créateurs. L’instruction envoie toujours la part du créateur vers les comptes de tokens associés canoniques possédés par pool_state.pool_creator ; l’appelant ne peut pas choisir un autre créateur ou destination. Si l’une des ATAs est manquante, le payeur finance sa création. Le CollectCreatorFee original reste appelable, donc un créateur qui veut signer pour sa propre collecte peut toujours le faire. Arguments — aucun. Comptes
Les deux nouveaux comptes sont ajoutés après system_program, et non insérés. Chaque compte de payer à system_program conserve la position qu’il avait avant la mise à niveau, donc la rupture est nette : une transaction construite selon l’ancienne disposition de quatorze comptes ne mésinterprète pas un vault comme une config — elle passe simplement trop peu de comptes et Anchor la rejette avec AccountNotEnoughKeys (3005) avant qu’aucune contrainte ne s’exécute. Les comptes restent obligatoires : ajoutez-les tous les deux en fin de liste et actualisez l’IDL ; il n’y a pas de chemin de compatibilité pour l’ancienne disposition.
Effet — identique à CollectCreatorFee ci-dessus : la part est résolue à partir de creator_fee_share ou amm_config, la part du protocole est enregistrée dans protocol_fees_token_{0,1}, la part du créateur est transférée vers les ATAs du créateur, les deux compteurs de créateurs sont mis à zéro, et recent_epoch est mis à jour. Retourne NoFeeCollect quand les deux compteurs sont zéro.

UpdatePoolStatus

Mettre en pause ou reprendre des opérations individuelles sur un pool. Le champ status est un masque de bits : Arguments
Comptes La clé admin est une clé publique compilée dans le programme (crate::admin::ID), pas l’autorité de mise à niveau BPF — la modifier nécessite une mise à niveau du programme. Consultez reference/program-addresses pour la valeur et security/admin-and-multisig pour qui la détient.

CreateAmmConfig

Créer un nouveau palier de frais. Arguments
Comptes Conditions préalables
  • Aucune AmmConfig existante avec le même index.
  • protocol_fee_rate + fund_fee_rate <= FEE_RATE_DENOMINATOR_VALUE.
Modifié en 2026-09 : les propriétaires de frais de la nouvelle config ne proviennent plus du signataire. create_amm_config écrit maintenant le protocol_fee_owner::ID codé en dur du programme dans protocol_owner et fund_fee_owner::ID dans fund_owner, au lieu de copier la clé du signataire admin dans les deux. Les adresses sont dans reference/program-addresses.Conséquences : les frais sur une nouvelle AmmConfig atterrissent dans les portefeuilles de frais dédiés plutôt que celui de l’admin. L’admin reste un signataire accepté pour la collecte — CollectProtocolFee / CollectFundFee acceptent amm_config.protocol_owner / fund_owner ou crate::admin::ID — donc rien n’a à être pivoté pour collecter ; ce qui a changé est seulement où les produits vont par défaut. Les comptes AmmConfig existants ne sont pas réécrits — tout ce qui y est stocké gouverne toujours, donc lisez toujours protocol_owner / fund_owner du compte au lieu d’assumer l’une ou l’autre valeur. Les paramètres 3 et 4 de UpdateAmmConfig les font toujours pivoter.

UpdateAmmConfig

Modifier les taux de frais ou la propriété sur une AmmConfig existante. Prend un param: u8 (quel champ mettre à jour) et une value: u64. La table de dispatch complète :
  • param = 0 → trade_fee_rate (affirme trade_fee_rate + creator_fee_rate < 1_000_000)
  • param = 1 → protocol_fee_rate (affirme ≤ 1_000_000 et + fund_fee_rate ≤ 1_000_000)
  • param = 2 → fund_fee_rate (affirme ≤ 1_000_000 et + protocol_fee_rate ≤ 1_000_000)
  • param = 3 → protocol_owner. La nouvelle clé n’est pas dans value : ajoutez-la comme remaining_accounts[0] (lecture seule est fine). Elle ne doit pas être la clé publique par défaut, et omettre le compte panique sur un unwrap().
  • param = 4 → fund_owner. Même mécanisme que 3.
  • param = 5 → create_pool_fee
  • param = 6 → disable_create_pool (toute value non-zéro désactive)
  • param = 7 → creator_fee_rate (affirme creator_fee_rate + trade_fee_rate < 1_000_000)
  • param = 8 → creator_fee_share_rate (affirme ≤ 1_000_000). Ajouté 2026-09-19. La part par défaut du protocole des frais créateurs sur ce palier ; voir products/cpmm/fees. Elle n’est pas liée à protocol_fee_rate, qui divise les frais commerciaux.
Tout autre param retourne InvalidInput. Les modifications sont signées par l’admin et affectent chaque pool lié à cette AmmConfig au prochain swap. Pas de migration ; les pools lisent simplement les nouvelles valeurs.

CreateCreatorFeeShare

Définir une part de protocole personnalisée des frais créateurs pour une paire (creator, amm_config), remplaçant AmmConfig.creator_fee_share_rate pour chaque pool que ce créateur possède sur ce palier de frais. Ajouté dans la mise à niveau de partage de frais créateurs 2026-09-19. Arguments
Comptes Conditions préalables
  • share_rate <= 1_000_000, sinon InvalidInput (6003).
  • Le PDA ne doit pas déjà exister — l’init d’Anchor échoue sur un deuxième appel pour la même paire. Pour modifier une taux, fermez le compte et recréez-le.
Postconditions
  • creator_fee_share stocke bump, creator, amm_config et share_rate.
  • Chaque CollectCreatorFee / CollectCreatorFeePermissionless ultérieur sur un pool créé par creator sous amm_config résout la part à partir de ce compte au lieu de la config.
Le créateur du pool n’est pas une partie à cette instruction et ne la signe pas. La taux est lue au moment de la collecte, donc un remplacement créé après que les frais aient déjà accumulé s’applique à ce solde accumulé aussi.

CloseCreatorFeeShare

Supprimer le remplacement. La paire revient à AmmConfig.creator_fee_share_rate. Arguments — aucun. Comptes Postconditions
  • Le compte est fermé et ses lamports vont à owner.
  • Les collectes pour cette paire résolvent la part à partir de amm_config.creator_fee_share_rate à nouveau — qui est 0 sauf si un admin a défini le paramètre 8 de UpdateAmmConfig.

CollectExcessLamports

Collecte admin des lamports assis au-dessus du minimum exempt de loyer sur les comptes que CPMM contrôle. Ajouté dans la mise à niveau 2026-09 pour que le protocole puisse récupérer le sur-financement que la réduction de loyer SIMD-0437 laisse derrière sur les comptes créés avant chaque étape. Seul l’excédent se déplace. Les soldes de tokens, les données de compte, les propriétaires, l’état du pool et la courbe restent inchangés, et l’instruction est un non-op par rapport à un compte déjà à son minimum — donc il est sûr de réexécuter après chaque étape de déploiement. Arguments — aucun. Comptes
Correction de l’ordre, 2026-09-19. Le programme fait maintenant deux passages sur remaining_accounts — chaque CPI du programme de tokens d’abord, puis les débits directs des PDAs possédés par CPMM. Les entrelacer avortait avec le UnbalancedInstruction du runtime (« la somme des soldes de compte avant et après l’instruction ne correspondent pas ») chaque fois qu’un PDA était débité avant un CPI, car les changements de lamports en attente de l’appelant ne sont vidés dans les comptes qu’un CPI porte réellement. Les appelants n’ont pas à grouper ou trier la liste eux-mêmes.
Comment chaque compte source est traité Le programme distribue sur le propriétaire du compte source : Parce qu’il prend une liste remaining_accounts non bornée, la taille de la transaction est la limite réelle — la même contrainte que la collecte côté portefeuille décrite dans solana-fundamentals/rent-and-reclaimable-rent. Erreurs courantes — InvalidOwner (6001, mauvais signataire), LamportsCalculateError (6015, l’aller-retour wSOL n’a pas nettoyé à zéro), et InsufficientFunds du chemin possédé par le programme quand un compte détient moins que son propre minimum de loyer. Pas de constructeur SDK. @raydium-io/raydium-sdk-v2 ne livre pas de constructeur pour cette instruction, et non plus le repo raydium-sdk-V2-demo — c’est un chemin admin. Encodez-la à la main, de la même façon que la collecte côté portefeuille dans solana-fundamentals/rent-and-reclaimable-rent le fait pour l’instruction du programme de tokens.

Matrice de changement d’état

Où aller ensuite

Sources :