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.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
* 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_mintpar ordre d’octets). - Aucun mint n’utilise une extension en dehors de la liste blanche CPMM (
TransferFeeConfig,MetadataPointer,TokenMetadata,InterestBearingConfig,ScaledUiAmount) — voirproducts/cpmm/accounts. Un mint dont le PDASupportMintAssociated(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 avecNotSupportMint(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. creatora au moinsinit_amount_0etinit_amount_1dans les ATAs respectifs.amm_config.disable_create_pool == false.
pool_state.lp_supply = sqrt(init_amount_0 * init_amount_1)— la racine carrée complète. Le créateur reçoitlp_supply − 100; les 100 unités de base verrouillées sont comptées danslp_supplymais jamais créées.- Donc
lp_mint.supply == pool_state.lp_supply − 100pour la durée de vie du pool. Toutes les mathématiques de part LP (dépôt, retrait) divisent parlp_supply, donc utilisez ce champ et ne substituez pas l’approvisionnement du mint en chaîne. Revient avecInitLpAmountTooLesssisqrt(...) < 100. observation_stateest initialisé ;observation_index = 0etpool_id = pool_state.key().- Les lamports
create_pool_feesont 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 = falseetcreator_fee_on = BothToken.Initializene supporte pas l’activation des frais créateurs — ce chemin estInitializeWithPermission.open_timeest augmenté àblock_timestamp + 1si l’appelant a passé une valeur<= block_timestamp. Les swaps sont rejetés avantopen_time; les dépôts et retraits fonctionnent immédiatement.
reference/error-codes)
InvalidInput— mints non triés, ou mints identiques.NotSupportMint— extension Token-2022 bloquée.ExceededSlippage— rarement ; siinit_amount_0/1ré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
Mathématiques
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).
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
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
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
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_statusautorise le swap.- Aucun mint en pause ou gelé pour cette autorité.
amount_in > 0.
ExceededSlippage—amount_out < minimum_amount_out.ZeroTradingTokens— le commerce s’arrondit à zéro.NotApproved— le pool est en pause pour les swaps viaUpdatePoolStatus.InvalidInput— les mints ne correspondent à aucun des mints du vault du pool.
SwapBaseOutput
Swap à sortie exacte.
Arguments
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
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
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
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
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
Conditions préalables
- Aucune
AmmConfigexistante avec le mêmeindex. 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(affirmetrade_fee_rate + creator_fee_rate < 1_000_000)param = 1→protocol_fee_rate(affirme≤ 1_000_000et+ fund_fee_rate ≤ 1_000_000)param = 2→fund_fee_rate(affirme≤ 1_000_000et+ protocol_fee_rate ≤ 1_000_000)param = 3→protocol_owner. La nouvelle clé n’est pas dansvalue: ajoutez-la commeremaining_accounts[0](lecture seule est fine). Elle ne doit pas être la clé publique par défaut, et omettre le compte panique sur ununwrap().param = 4→fund_owner. Même mécanisme que3.param = 5→create_pool_feeparam = 6→disable_create_pool(toutevaluenon-zéro désactive)param = 7→creator_fee_rate(affirmecreator_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 ; voirproducts/cpmm/fees. Elle n’est pas liée àprotocol_fee_rate, qui divise les frais commerciaux.
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
Conditions préalables
share_rate <= 1_000_000, sinonInvalidInput(6003).- Le PDA ne doit pas déjà exister — l’
initd’Anchor échoue sur un deuxième appel pour la même paire. Pour modifier une taux, fermez le compte et recréez-le.
creator_fee_sharestockebump,creator,amm_configetshare_rate.- Chaque
CollectCreatorFee/CollectCreatorFeePermissionlessultérieur sur un pool créé parcreatorsousamm_configré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 est0sauf si un admin a défini le paramètre8deUpdateAmmConfig.
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.
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
products/cpmm/code-demos— exemples TypeScript exécutables pour ce qui précède.reference/error-codes— la table d’erreur Anchor complète.products/cpmm/fees— le modèle d’accumulation de frais que les instructionsCollect*Feedrainent.

