Cette page est traduite automatiquement par IA. La version anglaise fait foi.Voir la version anglaise →
L’invariant
Le CPMM maintient l’invariant classique de produit constant sur ses deux coffres : oùx est le solde du coffre0 après les frais de transfert Token-2022 à la réception, et de même pour y. Chaque swap doit laisser k' ≥ k après comptabilisation des frais commerciaux crédités aux LP (les buckets protocole, fonds et créateur ne sont pas comptabilisés dans k — ils se trouvent dans le coffre mais sont exclus de la vue de la courbe, voir Frais sur la courbe ci-dessous). k croît donc de manière monotone au fil du temps à mesure que les LP accumulent les frais.
Les parts LP sont évaluées par les réserves du pool, non par k :
Brûler ΔLP tokens LP retourne exactement ΔLP × x / lpSupply de token0 et ΔLP × y / lpSupply de token1. Ni la courbe ni k ne bougent lors du dépôt ou du retrait — seuls les swaps changent le prix.
Modèle de frais sur le chemin du swap
Le CPMM applique deux frais évalués indépendamment sur chaque swap :- Le frais commerciaux est prélevé du côté de l’entrée, facturé au taux
AmmConfig.trade_fee_rate. Il est ensuite divisé en parts LP, protocole et fonds (la part LP reste dans le coffre et augmentek; les parts protocole et fonds sont extraites de la comptabilité du coffre). - Le frais créateur (actif uniquement quand
enable_creator_fee == true) est facturé au tauxAmmConfig.creator_fee_rate. Il est prélevé du côté de l’entrée ou du côté de la sortie selonPoolState.creator_fee_onet la direction du swap (voirproducts/cpmm/fees). C’est son propre bucket — jamais une tranche des frais commerciaux.
La part du protocole dans les frais créateur n’apparaît nulle part sur cette page, et c’est délibéré. Elle est appliquée quand
CollectCreatorFee déplace les frais accumulés entre deux compteurs que la courbe exclut déjà — pas pendant un swap. Les mathématiques du swap, les devis et k sont identiques avec et sans elle. Voir products/cpmm/fees.FEE_RATE_DENOMINATOR = 1_000_000trade_fee_rate— deAmmConfig, par exemple2500= 0,25 % du côté de volume pertinentcreator_fee_rate— deAmmConfig, par exemple1000= 0,10 % du côté de volume pertinentprotocol_fee_rate,fund_fee_rate— dénominés en unités de1/FEE_RATE_DENOMINATORdes frais commerciaux, non du volume
protocol_fee + fund_fee + creator_fee est détenu dans les coffres mais suivi séparément sur l’état du pool (protocol_fees_token*, fund_fees_token*, creator_fees_token*). Quand le contrôle d’invariant de produit constant vérifie k' ≥ k, il utilise les soldes du coffre moins les trois frais accumulés mais non collectés — donc les LP ne capturent que lp_fee.
Voir products/cpmm/fees pour les instructions de collecte et les exemples numériques détaillés.
SwapBaseInput (entrée exacte)
« L’utilisateur nous donne exactementamount_in du mint d’entrée et reçoit au moins minimum_amount_out du mint de sortie. »
En ignorant Token-2022 pour un moment :
Δx_net = amount_in_after_trade_fee.
Le programme met ensuite à jour la comptabilité du coffre de sorte que la portion de trade_fee due au protocole/fonds/créateur se trouve dans des buckets « accumulés » (non inclus dans le prochain x de la courbe), tandis que la part LP rejoint x pour le prochain swap.
Token-2022 du côté de l’entrée
Si le mint d’entrée a une extension de frais de transfert, le mint déduit ses frais lors du transfert de l’utilisateur → coffre. Donc le coffre reçoit réellementamount_in − transfer_fee_in(amount_in). Le programme CPMM calcule donc :
amount_in_after_trade_fee. C’est important car le prix de la courbe est calculé sur le montant net qui a atterri dans le coffre, non sur le montant annoncé par l’utilisateur.
Token-2022 du côté de la sortie
Si le mint de sortie a des frais de transfert, le pool envoieamount_out de son coffre à l’utilisateur. Le mint va alors prélever ses frais en sortie, donc l’utilisateur reçoit amount_out − transfer_fee_out(amount_out). Le programme calcule amount_out à partir de la courbe comme d’habitude, mais c’est la responsabilité de l’intégrateur de convertir le nombre « envoi du coffre » du pool en nombre « réception de l’utilisateur » lors de l’affichage des devis.
Vérification du slippage
Après le calcul deamount_out :
minimum_amount_out de sorte que la constante de slippage soit dénominée en ce que l’utilisateur recevra réellement, non en ce que le coffre envoie.
SwapBaseOutput (sortie exacte)
« L’utilisateur recevra exactementamount_out du mint de sortie et est disposé à payer jusqu’à maximum_amount_in du mint d’entrée. »
En inversant la courbe pour Δx_net :
Le plafond est important — il garantit k' ≥ k après troncature entière. Ensuite :
gross_needed.
Vérification du slippage
Exemple détaillé
État du pool, en ignorant Token-2022 :x = 1_000_000_000_000(1 000 000,000000 de token0, 6 décimales)y = 2_000_000_000_000(2 000 000,000000 de token1, 6 décimales)AmmConfig:trade_fee_rate = 2500,protocol_fee_rate = 120_000,fund_fee_rate = 40_000,creator_fee_rate = 0
SwapBaseInput avec amount_in = 1_000_000_000 (1 000,000000 de token0). Les frais créateur sont désactivés (enable_creator_fee = false).
enable_creator_fee = true avec creator_fee_rate = 1000 (0,10 %) du côté de l’entrée, le programme facturerait total_input_fee = ceil(1_000_000_000 * 3500 / 1_000_000) = 3_500_000, puis le diviserait en creator_fee = 1_000_000 et trade_fee = 2_500_000. L’arithmétique protocole/fonds/LP sur trade_fee est inchangée par rapport à l’exemple ci-dessus — les frais créateur sont leur propre bucket, accumulés dans creator_fees_token0 et exclus de curve_x avec les buckets protocole et fonds.
Si le mint d’entrée a des frais de transfert Token-2022 de 1 %, le coffre reçoit 990_000_000 tokens au lieu de 1_000_000_000, et chaque calcul ultérieur utilise ce montant net.
Règle de mise à jour de l’observation
À chaque swap, le programme évalue s’il faut pousser une nouvelle observation dans le tampon circulaire :- Prix cumulatif, pas prix au comptant. Une seule observation n’est pas un prix. Pour obtenir un TWAP du temps
t0au tempst1, lisez les observations les plus proches de chaque extrémité et calculez(cumulative(t1) − cumulative(t0)) / (t1 − t0). - Les échantillons sont limités en débit. Les swaps consécutifs dans le même slot peuvent partager une observation. Lire une observation immédiatement après un swap peut donc sembler obsolète d’un slot — c’est normal.
products/clmm/accounts.
Frais sur la courbe
C’est la partie subtile et vaut la peine d’être soulignée. L’arithmétique de la courbe fonctionne contre les soldes du coffre nets — c’est-à-dire le solde SPL brut moins les frais accumulés du protocole, des fonds et du créateur (les trois sont des buckets indépendants — voirproducts/cpmm/fees). Une image concrète :
- Ne pas faire de devis à partir des soldes bruts. Soustrayez d’abord les champs de frais accumulés, ou appelez
SwapBaseInputcomme une simulation et prenez son retour. CollectProtocolFeedéplace les tokens hors du coffre. Après la collecte,raw_vault_balancebaisse maiscurve_balancereste inchangé ; le prix du pool ne bouge pas. C’est délibéré.
Précision et débordement
- Toute l’arithmétique de la courbe utilise des intermédiaires
u128pour éviter le débordement surx * y. - La division arrondit vers zéro sauf pour le
Δx_netdeSwapBaseOutput, qui arrondit vers le haut, et le calcul des frais, qui arrondit vers le haut sur letrade_feeet vers le bas sur les sous-divisions. Ces directions d’arrondi sont choisies pour que l’invariant ne diminue jamais en raison de la troncature entière. - Les pools avec des ratios de coffre extrêmes (milliards : 1) peuvent atteindre des planchers de précision sur les petits trades ; le programme retourne
ZeroTradingTokensdans ce cas. Voirreference/error-codes.
Où aller ensuite
products/cpmm/fees— la sémantique complète des niveaux de frais et de collecte.products/cpmm/instructions— les instructions qui invoquent ces mathématiques.algorithms/constant-product— la dérivation et les cas limites dex · y = kpartagés entre AMM v4 et CPMM.
raydium-io/raydium-cp-swap— mathématiques du swap dansstates/curve.rs- Rapports d’audit Raydium liés dans
security/audits

