Skip to main content
Cette page est traduite automatiquement par IA. La version anglaise fait foi.Voir la version anglaise →
Cette page s’accompagne de products/clmm/accounts (ce que sont les comptes) et products/clmm/math (ce que sont les mathématiques). Elle fait autorité pour les arguments et l’ordre des comptes ; les dispositions d’octets spécifiques proviennent de l’IDL.La mise à niveau du programme 2026-09 a reconstruit CLMM sur Anchor 1.0.2 / Solana 3.1.10, a ajouté l’instruction admin CollectExcessLamports, et a modifié ce que CreateAmmConfig écrit dans 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-30.La mise à niveau du programme 2026-10-22 renomme CreatePermissionedPool en CreateCustomizablePoolV2, la rend appelable par n’importe qui, et supprime le compte Permission avec ses deux instructions admin. Consultez l’entrée du journal des modifications du 2026-10-22.

Inventaire des instructions

Il n’y a pas d’instruction d’initialisation de tableau de ticks, et aucune n’est nécessaire. Un tableau de ticks est créé à l’intérieur OpenPosition* / IncreaseLiquidity* par TickArrayState::get_or_create_tick_array, payé par payer. Passez le PDA du tableau de ticks (possiblement encore non initialisé, appartenant au système) en tant que tick_array_lower / tick_array_upper et le programme l’alloue s’il est manquant. OpenLimitOrder fait de même pour son unique tick_array.
La plupart des instructions réservées aux administrateurs (CreateAmmConfig, UpdateAmmConfig, UpdatePoolStatus, CreateOperationAccount, UpdateOperationAccount, CloseProtocolPosition) sont contrôlées par la clé publique admin codée en dur du programme. CreateSupportMintAssociated / CloseSupportMintAssociated acceptent soit la clé publique admin soit une clé de propriétaire de support-mint dédiée ; CollectExcessLamports accepte soit la clé publique admin soit un portefeuille dédié de collecte de lamports. Les instructions admin du flux de récompenses (TransferRewardOwner, CollectRemainingRewards) sont contrôlées par le financeur de récompenses, pas par l’admin du programme. Le suffixe V2 signifie « supporte Token-2022 sur les coffres-forts / NFT, nécessite l’emplacement d’extension bitmap ». Le SDK choisit V2 par défaut pour les nouveaux pools.

CreatePool

Arguments
Comptes (abrégés)
Les emplacements 10 et 11 sont par mint, pas « SPL Token puis Token-2022 ». Chacun est contraint par mint::token_program sur le mint correspondant, donc pour un pool dont token_mint_0 est Token-2022 et token_mint_1 est SPL classique, vous devez passer Token-2022 à l’emplacement 10 et SPL Token à l’emplacement 11. CreateCustomizablePool et CreateCustomizablePoolV2 utilisent les mêmes deux emplacements.
Préconditions
  • token_mint_0 < token_mint_1 par ordre d’octets.
  • amm_config.disable_create_pool == false.
  • Les mints ne sont pas rejetés par la liste blanche d’extension Token-2022.
Postconditions
  • pool_state.sqrt_price_x64 = sqrt_price_x64, tick_current = floor(log_{1.0001}(price)).
  • pool_state.liquidity = 0 (aucune position encore).
  • pool_state.fee_on = FromInput (défaut hérité).
  • pool_state.dynamic_fee_info est mis à zéro (frais dynamiques désactivés).

CreateCustomizablePool

Recommandé pour les nouveaux pools. Même effet que CreatePool plus le mode de collecte des frais par pool et une activation optionnelle des frais dynamiques. Arguments
Comptes — exactement les 13 comptes déclarés de CreatePool. dynamic_fee_config n’est pas un compte déclaré.
Quand enable_dynamic_fee = true, le DynamicFeeConfig à capturer doit être fourni en tant que dernier remaining_account — le gestionnaire lit ctx.remaining_accounts.last(). Tout PDA de contournement SupportMintAssociated doit donc venir avant lui, ou le programme capture le mauvais compte et échoue la désérialisation. L’omettre alors que le drapeau est défini échoue avec AccountLack.
Préconditions — identiques à CreatePool. Si enable_dynamic_fee = false, aucun remaining_account n’est requis et tous ceux qui sont passés ne sont scannés que pour les enregistrements de support-mint. Postconditions
  • pool_state.fee_on défini à la variante CollectFeeOn choisie.
  • Si les frais dynamiques ont été activés : pool_state.dynamic_fee_info est initialisé à partir du DynamicFeeConfig fourni (cinq paramètres d’étalonnage copiés ; champs d’état mis à zéro).
  • Sinon : pool_state.dynamic_fee_info est mis à zéro (= frais dynamiques inactifs à jamais pour ce pool).
fee_on et le bit d’activation des frais dynamiques sont définis uniquement à la création du pool. Il n’y a pas de mise à niveau sur place — les pools créés via le CreatePool hérité ne peuvent pas acquérir rétroactivement les frais dynamiques ou les frais unilatéraux. Les nouveaux déploiements doivent utiliser cette instruction par défaut.

CreateCustomizablePoolV2

Les instructions CreatePool et CreateCustomizablePool dérivent l’adresse PDA du pool à partir de ["pool", amm_config, token_mint_0, token_mint_1], ce qui signifie qu’il existe exactement une adresse de pool canonique par triplet (config, mint0, mint1) — une deuxième tentative d’init aux mêmes seeds échoue. CreateCustomizablePoolV2 lève cette restriction en intégrant un seed_index: u16 fourni par le client dans les seeds de la PDA du pool, permettant plusieurs pools pour la même paire et le même palier de frais — chacun à sa propre adresse. N’importe qui peut l’appeler. Tout le reste concernant le pool est identique à CreateCustomizablePool : il prend les mêmes CreateCustomizableParams et supporte les frais unilatéraux et l’opt-in pour les frais dynamiques.
Jusqu’à la mise à jour du 2026-10-22, cette instruction s’appelait CreatePermissionedPool et exigeait que le payeur détienne une PDA Permission émise par un administrateur. La mise à jour l’a renommée, a supprimé le compte permission et a supprimé la machinerie des permissions. Le discriminateur a changé avec le nom, donc les clients construits contre CreatePermissionedPool doivent être reconstruits.
Arguments
Comptes remaining_accounts : les PDAs du registre de support-mint quand un mint Token-2022 en a besoin, et la DynamicFeeConfig en dernier quand enable_dynamic_fee = true — comme dans CreateCustomizablePool. Préconditions
  • seed_index != 0. Un seed_index de 0 est réservé aux pools hérités et est rejeté ici ; la composante seed [0, 0] est ce qui fait qu’une adresse de pool hérité s’effondre à la forme classique à quatre seeds.
  • Aucun pool n’existe déjà à l’adresse dérivée.
  • Mêmes règles de mint / liste d’autorisation que CreatePool.
Postconditions
  • Un nouveau pool_state existe à l’adresse dérivée du seed_index, avec pool_state.seed_index = seed_index.
  • Tous les autres post-états correspondent à CreateCustomizablePool (mode de frais, frais dynamiques optionnels).
Parce que pool_creator n’est pas vérifié, n’importe quel payeur peut écrire n’importe quelle adresse dans pool_state.owner. Cette adresse peut appeler InitializeReward sur le pool, mais ce n’est pas une preuve de qui a créé le pool. Les intégrateurs ne doivent pas étiqueter ou classer les pools V2 par leur owner.

OpenPositionV2 / OpenPositionWithToken22Nft

Créer une nouvelle position à l’intérieur d’un pool existant. Arguments
Comptes — les deux variantes ont des listes de comptes différentes. OpenPositionV2 en déclare 22 ; OpenPositionWithToken22Nft en déclare 20. OpenPositionV2, dans l’ordre : OpenPositionWithToken22Nft est la même liste avec metadata_account (5) et metadata_program (19) supprimés — il écrit les métadonnées de la position via l’extension de métadonnées Token-2022 sur le mint du NFT à la place — donnant 20 comptes. Son position_nft_mint est un Signer nu et position_nft_account un UncheckedAccount.
tick_array_bitmap_extension n’est pas un compte déclaré sur l’une ou l’autre variante. Quand la plage de la position se situe en dehors du tick_array_bitmap en ligne du pool (±512 tableaux de ticks), ajoutez la PDA TickArrayBitmapExtension aux seeds ["pool_tick_array_bitmap_extension", pool_state] comme remaining_accounts[0].
Mathématiques — voir products/clmm/math. Étant donné base_flag, le programme résout soit liquidity soit (amount_0_max, amount_1_max) en L réel et les montants de tokens réels consommés. Préconditions
  • tick_lower < tick_upper, tous deux multiples de pool.tick_spacing, dans [MIN_TICK, MAX_TICK].
  • Les deux PDAs de tableaux de ticks sont passées. Elles n’ont pas besoin d’exister déjà — get_or_create_tick_array alloue une manquante à la charge du payer à l’intérieur de cette instruction. Il n’y a pas d’instruction d’init-tick-array séparée.
  • L’utilisateur a au moins amount_0_max et amount_1_max dans les ATAs sources.
Postconditions
  • personal_position existe, liquidity défini, fee_growth_inside_last capturé.
  • Les entrées du tableau de ticks à tick_lower et tick_upper mises à jour (liquidity_gross += L, liquidity_net ± L, snapshots de croissance des frais maintenus).
  • pool_state.liquidity += L si la position est en plage (tick_lower ≤ tick_current < tick_upper).
  • Le mint du NFT de la position enregistre pool_state comme autorité de gel. L’autorité de mint est supprimée après que le seul NFT soit frappé. L’enregistrement de l’autorité de gel ne change pas l’état du compte de tokens du NFT.
  • Le compte de tokens du NFT reste dégelé sauf si l’instruction est OpenPositionV2 ou OpenPositionWithToken22Nft et que l’autorité de gel de l’un ou l’autre mint du coffre correspond à la liste des émetteurs restreints du CLMM. Seul ce chemin V2 correspondant gèle le compte. OpenPosition V1 ne gèle pas.
Erreurs courantes — TickInvalidOrder (tick_lower >= tick_upper), TickAndSpacingNotMatch (une extrémité n’est pas un multiple de tick_spacing), InvalidTickIndex (en dehors de [MIN_TICK, MAX_TICK]), MissingTickArrayBitmapExtensionAccount (plage en dehors du bitmap en ligne et l’extension n’a pas été ajoutée), NotApproved (pool_state.status bloque l’ouverture), ZeroAmountSpecified.
Le gel de position n’ajoute pas de comptes d’instruction déclarés ni d’arguments. Les clients peuvent ouvrir ces positions avec les mises en page V2 existantes. Le comportement est sélectionné on-chain à partir de vault_0_mint et vault_1_mint.

IncreaseLiquidityV2

Ajouter de la liquidité à une position déjà ouverte. Arguments
Comptes — 15, et non dérivables de OpenPosition : il n’y a pas de rent, pas de system_program, pas de associated_token_program et pas de compte de métadonnées. Ajoutez en préfixe la PDA TickArrayBitmapExtension comme remaining_accounts[0] quand la plage de la position se situe en dehors du bitmap en ligne. Effet
  • Transfère amount_0_actual / amount_1_actual de l’utilisateur → coffres.
  • Incrémente personal_position.liquidity et pool_state.liquidity (si en plage), et le liquidity_gross / liquidity_net des ticks d’extrémité en conséquence.
  • Collecte les frais et récompenses dus depuis le dernier accès et les crédite à token_fees_owed_{0,1} / reward_amount_owed. Ceux-ci ne sont payés que sur DecreaseLiquidity / DecreaseLiquidityV2, pas sur l’augmentation — il n’y a pas d’instruction de collecte autonome.

DecreaseLiquidityV2

Retirer de la liquidité d’une position. Arguments
Comptes — 16, et pas la même forme ou le même ordre que IncreaseLiquidityV2 : personal_position et pool_state sont échangés, les coffres viennent avant les tableaux de ticks, les comptes côté utilisateur sont nommés recipient_token_account_*, et il y a un memo_program supplémentaire. Comptes restants — trois par récompense active collectée, dans l’ordre reward_token_vault(W), recipient_token_account(W), reward_vault_mint. Ajoutez en préfixe la PDA TickArrayBitmapExtension quand la plage de la position se situe en dehors du bitmap en ligne.
C’est aussi la seule façon de collecter les frais et récompenses. Pour collecter sans changer la position, appelez-la avec liquidity = 0, amount_0_min = 0, amount_1_min = 0.
Effet
  • Calcule (amount_0, amount_1) pour le L supprimé étant donné le sqrt_price_x64 actuel.
  • Règle les frais/récompenses accumulés depuis le dernier accès, comme IncreaseLiquidity.
  • Transfère amount_0 + fees_owed_0 et amount_1 + fees_owed_1 hors des coffres vers l’utilisateur.
  • Décrémente les compteurs de liquidité ; si le nouveau personal_position.liquidity == 0, la position est éligible pour ClosePosition.
Slippage — amount_0_min et amount_1_min sont les minimums que l’utilisateur accepte nets des frais de transfert Token-2022 du côté de la sortie.

ClosePosition

Brûler le NFT de position et fermer PersonalPositionState. Comptes déclarés Comptes restants
  • NFT non gelé : aucun requis ; un compte de pool supplémentaire est inoffensif car le gestionnaire ne le lit pas.
  • NFT gelé : ajouter personal_position.pool_id comme premier compte restant. Le programme le charge en tant que PoolState et utilise ses graines PDA pour signer le dégel.
Préconditions
  • personal_position.liquidity == 0.
  • tokens_fees_owed_{0,1} == 0.
  • Tous les compteurs de récompense reward_amount_owed == 0.
(C’est-à-dire, collecter tout et diminuer à zéro d’abord.) Effet
  • Si le compte de token NFT est gelé, vérifie que le premier compte restant est égal à personal_position.pool_id, puis le dégèle avec le PDA du pool.
  • Brûle le NFT.
  • Ferme le compte de token NFT et personal_position, remboursant le loyer à nft_owner. Si le NFT de position utilise Token-2022, il ferme également le mint NFT ; les mints Token SPL classiques ne peuvent pas être fermés et restent avec une offre zéro.
Le dégel, la combustion et la fermeture sont atomiques. Le NFT ne peut pas devenir transférable entre ces étapes. Rupture client conditionnelle — la disposition IDL déclarée est inchangée, donc les clients hérités continuent de fermer les positions existantes et non gelées. Un constructeur hérité qui omet le compte de pool restant échoue avec AccountLack lors de la fermeture d’une position gelée. Passer le pool pour chaque fermeture est la stratégie compatible la plus simple.

SwapV2

Parcourir la courbe de liquidité ; entrée exacte ou sortie exacte selon is_base_input. Arguments
Comptes (abrégés) Les appelants passent une liste classée de tableaux de ticks couvrant le parcours de swap attendu ; le programme en utilise autant que nécessaire. Le SDK calcule cette liste via PoolUtils.computeAmountOutFormat ou le point de terminaison de devis de l’API. Préconditions
  • pool_state.status autorise le swap.
  • now >= open_time.
  • sqrt_price_limit_x64 est du bon côté de sqrt_price_x64 pour la direction.
Erreurs courantes — TooLittleOutputReceived (slippage exact-in), TooMuchInputPaid (slippage exact-out), SqrtPriceLimitOverflow, NotEnoughTickArrayAccount, InvalidFirstTickArrayAccount, MissingTickArrayBitmapExtensionAccount, LiquidityInsufficient, NotApproved (bit de swap défini sur pool_state.status). CLMM n’a pas de variante ExceededSlippage — ce nom est celui de CPMM — et pas de TickArrayNotFound. Ce que SwapV2 fait en interne et que les appelants doivent savoir (version post-2025) :
  1. Surcharge de frais dynamique — si pool.dynamic_fee_info est non nul, le programme met à jour l’accumulateur de volatilité en utilisant la distance de tick parcourue depuis le dernier swap (avec les règles de filtre/décroissance de products/clmm/fees) et ajoute un dynamic_fee_component en plus de AmmConfig.trade_fee_rate. Les frais totaux sont plafonnés à 10 % (MAX_FEE_RATE_NUMERATOR / 1_000_000).
  2. Appariement des ordres limites — lorsque le parcours des prix croise un tick qui contient des ordres limites ouverts, le programme remplit d’abord la liquidité des ordres limites disponibles à ce tick (FIFO par order_phase), puis procède le long de la courbe de liquidité LP. Les montants remplis mettent à jour tick.unfilled_ratio_x64 et tick.part_filled_orders_remaining pour un règlement ultérieur ; les ordres eux-mêmes restent non dépensés jusqu’à ce que leur propriétaire appelle SettleLimitOrder.
  3. Routage des frais unilatéral — lorsque pool.fee_on = Token0Only ou Token1Only, l’étape de swap calcule toujours le même échange entrée-sortie ; les frais sont ensuite acheminés vers le côté configuré. Pour les directions où le côté de frais configuré est la sortie, les frais sont déduits de la sortie du swap (l’utilisateur reçoit out − fee) ; pour les directions où c’est l’entrée, le comportement correspond à FromInput. Voir is_fee_on_input(zero_for_one) et is_fee_on_token0(zero_for_one) sur PoolState.
Swap (V1) implémente les mêmes frais dynamiques, routage des frais unilatéral et appariement des ordres limites que SwapV2 ; la seule fonctionnalité qui lui manque est la prise en charge de Token-2022 — les deux coffres doivent être du Token SPL classique. Les pools avec n’importe quel mint Token-2022 doivent être échangés via SwapV2. L’agrégateur et le SDK préfèrent déjà V2 pour chaque jambe CLMM, donc les appelants n’ont pas à se brancher sur le type de mint.

OpenLimitOrder

Placer un ordre de vente à un tick spécifique. L’ordre se trouve dans une cohorte FIFO par tick et se remplit à mesure que le prix passe. Arguments
Comptes (abrégés) Comptes restants — [0] tick_array_bitmap_extension, requis uniquement lors de l’initialisation d’un tableau de ticks dont l’index de départ se situe en dehors de la bitmap en ligne du pool. Ne passer rien sinon.
Il n’y a pas de compte rent : la structure se termine à system_program, 13 comptes déclarés. Un rent égaré en position 14 se retrouve exactement où l’extension bitmap optionnelle est lue, donc l’ordre semble fonctionner jusqu’à la première fois où un tableau de ticks en dehors de la bitmap en ligne doit être créé — et échoue ensuite.
Changement de liste de comptes (version 2026-07). OpenLimitOrder prend maintenant aussi les comptes du côté sortie — output_token_account, output_vault et output_vault_mint — en plus du côté entrée. Ils sont utilisés uniquement pour la validation : le programme rejette l’ordre si le compte de token d’entrée ou de sortie du propriétaire est gelé. Cela garantit qu’un remplissage peut réellement être réglé vers l’ATA de sortie du propriétaire, ce qui importe pour les mints Token-2022 avec liste d’autorisation / gelés par défaut (par exemple, les tokens autorisés) où un compte peut ne pas encore être dégelé. Les clients construits par rapport à l’ancienne liste de comptes unilatérale doivent ajouter les trois comptes de sortie.
Préconditions
  • Ni input_token_account ni output_token_account n’est gelé (sinon NotApproved).
  • pool_state.status autorise à la fois les opérations de swap (bit 4) et d’ordre limite (bit 5) (sinon NotApproved).
  • tick_index % pool.tick_spacing == 0 et dans [MIN_TICK, MAX_TICK].
  • tick_index est du bon côté de pool.tick_current pour la direction choisie (vendre token0 → le tick doit être au-dessus du courant, et vice versa). Vendre à un tick déjà croisé serait immédiatement appairé et est rejeté.
Postconditions
  • limit_order existe, capturant tick.order_phase et tick.unfilled_ratio_x64 au moment de l’ouverture.
  • tick.orders_amount += amount (dans la cohorte actuelle).
  • limit_order_nonce.order_nonce += 1.
  • OpenLimitOrderEvent émis.
Erreurs courantes — NotApproved (compte de token d’entrée ou de sortie gelé, ou le pool a le swap / ordre limite désactivé), ZeroAmountSpecified (amount == 0 après les frais de transfert du côté entrée), InvalidLimitOrderAmount (le montant produirait une sortie inférieure à 1 unité de base à ce tick, ou déborderait u64), InvalidTickIndex (en dehors de [MIN_TICK, MAX_TICK], ou du mauvais côté de tick_current pour la direction choisie), TickAndSpacingNotMatch (tick_index % pool.tick_spacing != 0), OrderPhaseSaturated.

IncreaseLimitOrder

Ajouter à un ordre ouvert existant. Uniquement appelable par le owner de l’ordre. Arguments
Comptes — 8, côté entrée uniquement. Il supprime le compte nonce, les trois comptes du côté sortie et system_program. Préconditions
  • limit_order.owner == signer.
  • L’ordre est toujours dans la même cohorte (tick.order_phase == limit_order.order_phase). Si la cohorte a déjà commencé à se remplir, l’ordre est partiellement réglé — l’appelant doit d’abord appeler DecreaseLimitOrder ou SettleLimitOrder pour avancer.
Effet
  • Transfère amount de l’ATA du propriétaire vers input_vault.
  • limit_order.total_amount += amount ; tick.orders_amount += amount.

DecreaseLimitOrder

Réduire ou annuler complètement un ordre ouvert. Rembourse le reste non rempli au propriétaire, plus toute sortie déjà réglée par les remplissages partiels passés. Arguments
Comptes — côtés token d’entrée et de sortie : Effet
  • Recalcule le montant rempli de l’ordre à partir du unfilled_ratio_x64 de la cohorte depuis l’ouverture.
  • Envoie la sortie remplie vers output_token_account.
  • Envoie amount de l’entrée non remplie vers input_token_account.
  • Met à jour limit_order en conséquence. Si le nouveau reste non rempli est zéro, le programme ferme le compte et rembourse le loyer au owner.

SettleLimitOrder

Transférez les jetons de sortie remplis au propriétaire sans modifier le reste non rempli de la commande. Utile quand les gardiens auto_withdraw veulent effectuer des paiements progressifs pour les remplissages partiels de longue durée. Appelant — soit le owner de la commande, soit le limit_order_admin du programme (un portefeuille opérationnel hors chaîne qui exécute une boucle de gardien automatisée). Le gardien n’a aucune autre autorité — il ne peut pas déplacer les fonds de l’utilisateur en dehors de l’envoi de la sortie remplie vers l’ATA owner de la commande. Comptes Effet
  • Calcule la sortie cumulative due en utilisant (limit_order.unfilled_ratio_x64, tick.unfilled_ratio_x64).
  • Transfère le delta vers output_token_account.
  • Met à jour limit_order.settled_output.
  • Ne ferme pas la commande ; elle reste ouverte pour toute entrée restante.

CloseLimitOrder

Fermez un compte de commande entièrement consommé. Le loyer est toujours retourné à limit_order.owner quel que soit le signataire. Appelant — soit owner soit limit_order_admin. Préconditions
  • La commande a un reste non rempli de zéro (soit amount == total_amount a été rempli et réglé, soit le propriétaire a précédemment réduit la commande à zéro et a oublié de la fermer).
Effet
  • Ferme limit_order ; le loyer est envoyé à limit_order.owner.

CreateDynamicFeeConfig (admin)

Créez un ensemble de paramètres réutilisable sous un index u16. Arguments
Comptes Erreurs courantes — InvalidDynamicFeeConfigParams si decay_period <= filter_period ou si un champ à valeur 0 est hors limites.

UpdateDynamicFeeConfig (admin)

Modifiez une DynamicFeeConfig existante. Les pools qui ont déjà capturé la configuration au moment de la création ne sont pas rétroactivement mis à jour ; seuls les pools nouvellement créés qui référencent cette configuration reprendront les nouvelles valeurs. Arguments — les mêmes cinq champs de calibrage que CreateDynamicFeeConfig (filter_period, decay_period, reduction_factor, dynamic_fee_control, max_volatility_accumulator) ; index est fixé à la création et n’est pas répassé ici.

CollectProtocolFee / CollectFundFee

Balayez les frais de protocole/fonds accumulés des coffres du pool vers un destinataire, en mettant à zéro les champs correspondants PoolState.protocol_fees_* / fund_fees_*. Ce n’est pas la disposition de CPMM — CLMM n’a pas de compte authority, et les champs destinataire sont nommés recipient_token_account_{0,1} plutôt que recipient_token_{0,1}_account. Arguments — amount_0_requested: u64, amount_1_requested: u64.
Modifié en 2026-09 : les nouvelles configurations ne prennent plus leurs propriétaires de frais du signataire. create_amm_config écrit maintenant le protocol_fee_owner::ID codé en dur du programme dans owner et fund_fee_owner::ID dans fund_owner. Avant, il copiait la clé du signataire admin dans les deux. Sur mainnet, ce sont déjà les mêmes clés stockées sur les 21 configurations existantes. Les adresses se trouvent dans reference/program-addresses.Les signataires acceptés ci-dessus sont inchangés. L’admin peut toujours collecter à partir de n’importe quelle configuration, et les comptes AmmConfig existants ne sont pas réécrits. Lisez owner / fund_owner du compte au lieu de supposer l’une ou l’autre valeur. Les paramètres UpdateAmmConfig 3 et 4 les font toujours tourner.

CollectExcessLamports

Balayage admin des lamports au-dessus du minimum exempt de loyer sur les comptes que CLMM contrôle. Il a été ajouté dans la mise à niveau 2026-09 pour récupérer le surfinancement que la réduction de loyer SIMD-0437 laisse sur les comptes créés avant chaque étape. Seul l’excédent se déplace. Les soldes de jetons, les données de compte, les propriétaires, l’état du pool et la courbe de prix restent inchangés. Un compte déjà à son minimum est laissé tel quel, donc l’instruction peut être réexécutée en toute sécurité après chaque étape de déploiement. Arguments : aucun. Comptes Portée : un pool par appel. CLMM n’a pas d’autorité de coffre à l’échelle du programme. Les coffres de chaque pool sont possédés par son propre PoolState. Chaque source du programme de jetons doit donc avoir le pool_state à l’emplacement 2 comme autorité : token_vault_0, token_vault_1, ou l’un des coffres de récompense de ce pool. Si vous passez le coffre d’un autre pool ou un compte de jetons d’un utilisateur, la vérification du propriétaire du programme de jetons échoue et l’instruction entière est annulée. Elle n’est pas ignorée. Les mints NFT de position ne peuvent pas être balayés, car leur autorité de mint est révoquée à l’ouverture de la position. Comment chaque compte source est traité Le programme effectue deux passages sur remaining_accounts : d’abord chaque CPI du programme de jetons, puis les débits directs. L’entrelacement des deux abandonne avec l’erreur UnbalancedInstruction du runtime, donc l’ordre est fixé dans le programme et vous n’avez pas à trier la liste vous-même.
Le passage 2 couvre les comptes dont le loyer a été payé par un utilisateur. Un PersonalPositionState ou LimitOrderState passé ici abandonne son excédent comme tout autre compte appartenant à CLMM. Il reste exempt de loyer et conserve ses données. Lorsqu’il est fermé ultérieurement, le propriétaire récupère ce que le compte détient à ce moment, qui après un balayage est le minimum de loyer actuel.
La taille de la transaction est la vraie limite sur le nombre de sources qui tiennent dans un appel. C’est la même contrainte que le balayage côté portefeuille décrit dans solana-fundamentals/rent-and-reclaimable-rent. Erreurs courantes :
  • NotApproved (6000) : mauvais signataire.
  • LamportsCalculateError (6052) : l’aller-retour wSOL n’a pas donné zéro.
  • Une erreur de non-correspondance du propriétaire du programme de jetons : une source de jetons n’est pas possédée par pool_state.
  • InsufficientFunds : un compte appartenant au programme détient moins que son propre minimum de loyer.
Pas de générateur SDK. @raydium-io/raydium-sdk-v2 n’expédie pas de générateur pour ce chemin admin. Encodez-le à la main à partir de l’IDL.

InitializeReward

Ajoutez un nouveau flux de récompense à un pool. Jusqu’à 3 flux peuvent être actifs à la fois. Arguments — une seule structure, param: InitializeRewardParam :
L’encodage sur le fil est les trois champs dos à dos, donc une instruction construite à la main n’est pas affectée — mais un client piloté par IDL doit passer un objet param plutôt que trois arguments positionnels. Comptes Préconditions
  • Moins de 3 flux actuellement actifs sur le pool.
  • Le financeur dépose total_emission = emissions_per_second × (end_time − open_time) de jetons de récompense dans le coffre dans le cadre de cette instruction.
  • Mint de récompense sur liste blanche par operation_state.

SetRewardParams

Prolongez, complétez ou modifiez le taux d’émission sur un flux de récompense existant. Généralement appelé par un créateur de pool ou le multisig Raydium. Les contraintes vivent sur chaîne : vous pouvez généralement prolonger end_time ou augmenter les émissions, pas les réduire rétroactivement. Vérifiez la liste des propriétaires de operation_state.

UpdateRewardInfos

Pur travail administratif — règle reward_growth_global_x64 à l’heure actuelle en multipliant emissions_per_second × Δt / liquidity. Appelé en interne par chaque instruction touchant la liquidité. Exposé comme une instruction autonome car les acteurs externes (UIs, cranks) veulent parfois le déclencher.

Collecte des récompenses

Il n’y a pas d’instruction de collecte de récompense autonome. Le programme n’expose pas de point d’entrée CollectReward, et l’IDL publié n’en a pas non plus.
Les récompenses dues à une position sont versées par DecreaseLiquidity / DecreaseLiquidityV2. Pour collecter sans modifier la position, appelez-la avec liquidity = 0, amount_0_min = 0, amount_1_min = 0. Les coffres de récompense et les comptes destinataires vont dans remaining_accounts en groupes de trois par récompense active, dans l’ordre reward_token_vault(W), recipient_token_account(W), reward_vault_mint. CollectRemainingRewards est une chose différente : il permet au financeur de récompense, après le end_time d’un flux, de balayer les jetons qui n’ont jamais été alloués à aucune position.

Matrice de changement d’état

Étapes suivantes

Sources :