Cette page est traduite automatiquement par IA. La version anglaise fait foi.Voir la version anglaise →
Quand CPI est le bon outil
Un programme personnalisé a du sens quand l’échange doit se produire de façon atomique avec d’autres changements d’état on-chain que seul votre programme peut effectuer. Cas courants :- Programmes de dépôt en garantie / ordres limités — l’utilisateur dépose un mint dans votre dépôt, votre programme surveille une condition de prix, et quand elle se déclenche, votre programme fait atomiquement un échange via Raydium et crédite le compte de l’utilisateur.
- Proxies d’agrégateurs — une instruction unique qui achemine un échange via Raydium et un ou plusieurs autres DEX, tous les sauts sous un seul contrôle de slippage détenu par votre programme.
- Coffres à composition automatique — déposez un LP ou un enjeu de ferme dans votre coffre, le coffre récolte les récompenses selon un calendrier, réapprovisionne la liquidité, émet des tokens de part.
- Coffres de stratégie — positions LP avec levier qui se rééquilibrent en échangeant via CLMM ; liquidateurs qui ferment des positions et échangent des garanties en une seule transaction.
- Plateformes de lancement de tokens avec déblocage personnalisé — votre programme détient des tokens de déblocage et les libère dans une pool Raydium selon un calendrier.
Modèles de composition
Modèle 1 : Proxy mince
Votre programme expose une instruction unique qui valide une certaine politique (p. ex. paires de mints autorisées, remise de frais pour les utilisateurs vérifiés) puis fait suivre à Raydium.Modèle 2 : Dépôt en garantie
Votre programme possède un PDA qui détient le mint d’entrée de l’utilisateur. À la déclenchement, le PDA signe un CPI à Raydium pour échanger son propre solde.CpiContext::new_with_signer. Voir Graines de signe PDA.
Modèle 3 : Multi-saut composé
Votre programme émet plusieurs CPI en une instruction, en appliquant une limite de slippage unique sur tous. Les instructions d’échange Raydium ont chacune leurs propresminimum_amount_out, mais vous les mettez à 0 (ou un plancher très lâche) et appliquent un strict minimum final vous-même après le dernier saut.
Modèle 4 : Coffre / stratégie
Votre programme détient des tokens LP ou un enjeu de ferme dans un PDA. Un gardien (ou l’utilisateur) appellecompound(), ce qui :
- Récolte les récompenses de la ferme.
- Échange les récompenses pour les tokens de pool (CPI dans CPMM ou CLMM).
- Dépose le produit brut dans le LP (un autre CPI).
- Enjeu le nouveau LP (un autre CPI).
Construction de liste de comptes
La structureAccounts du programme appelant reflète l’ordre des comptes du programme Raydium, mais la plupart des comptes du côté Raydium sont UncheckedAccount car Raydium les valide lui-même. Vous n’ajoutez des contraintes que sur les comptes que vous possédez :
UncheckedAccount sur ceux de Raydium — n’est pas de la paresse. Le récepteur valide le sien ; la double validation à l’appelant gaspille juste CU et risque de se désynchroniser quand Raydium envoie un champ de nouvelle disposition de struct.
L’appel CPI lui-même
Graines de signe PDA
Le CPI ne réussit que si le PDA passé en tant queauthority correspond à la dérivation que l’appelant prétend. Les deux doivent s’accorder sur :
- La séquence d’octet de seed (ici
[b"escrow", user.key().as_ref()]). - Le bump.
- L’ID du programme appelant (votre programme, pas celui de Raydium).
authority couvre la transaction et que l’ATA d’entrée est détenu par cette autorité. La validation se produit dans anchor_spl::token::transfer : le champ authority de l’ATA doit être égal au signataire.
Bug commun : passer user comme autorité (et transférer depuis escrow_input_ata qui est détenu par le PDA du dépôt en garantie). Le programme Token SPL rejette avec owner mismatch. Faites toujours correspondre le champ authority au propriétaire de l’ATA.
Comptes restants
Plusieurs instructions Raydium prennent une liste de longueur variable de comptes ajoutés après les comptes fixes — comptes restants.- CLMM
SwapV2: 1–8 comptesTickArrayStatepour les tableaux de ticks que l’échange peut traverser, dans la direction de l’échange. - Farm v6
Deposit/Harvest/Withdraw: paires(reward_vault, user_reward_ata), une paire par slot de récompense actif. - Mints Token-2022 avec crochet de transfert : le programme de crochet de transfert plus tous les comptes dont le crochet a besoin.
Budget de calcul pour les appels composés
Un CPI coûte ~1 500 CU pour le cadre d’appel lui-même ; l’utilisation de CU propre de l’appelé s’empile dessus. Budget approximatif par CPI Raydium :| Appel | CU (Token SPL) | CU (Token-2022) |
|---|---|---|
| CPMM swap_base_input | ~150 000 | ~200 000 |
| CLMM swap_v2 (un seul tableau de ticks) | ~180 000 | ~230 000 |
| CLMM swap_v2 (traverse 2 ticks) | ~220 000 | ~270 000 |
| Farm v6 deposit | ~120 000 | ~150 000 |
| Farm v6 harvest (par slot de récompense) | +30 000 | +40 000 |
| AMM v4 swap_base_in | ~140 000 | n/a |
harvest → swap A → swap B → deposit LP → stake LP atteint facilement 700k CU.
Définissez toujours une limite ComputeBudgetProgram::set_compute_unit_limit explicite :
Propagation d’erreur
Les programmes Raydium retournent les erreurs Anchor avec des codes d’erreur stables. Votre programme appelant les voit commeErr(ProgramError::Custom(code)). Frayez par défaut :
sdk-api/anchor-idl) ; les nouveaux codes s’ajoutent à la fin, les codes existants ne changent jamais de signification.
Exemple complet travaillé : escrow d’ordre limité
Flux :open_order— l’utilisateur déposeamount_indeinput_mintdans le PDA du dépôt en garantie ; enregistre lemin_amount_outcible et l’expiration.execute_order— n’importe qui (gardien) appelle avec les comptes de pool actuels. Le programme vérifie que le devis actuel ≥min_amount_out, puis CPI l’échange Raydium et garde la sortie en dépôt en garantie.claim— l’utilisateur retire le mint de sortie du dépôt en garantie.
Test
Tirant les programmes Raydium dans un validateur local pour les tests d’intégration (depuisAnchor.toml) :
anchor test les récupère depuis mainnet au démarrage. Voir sdk-api/rust-cpi.
Pièges spécifiques à la composition
Réentrance
Solana n’a pas de vraie réentrance — un CPI ne peut pas rappeler le programme d’origine dans la même invocation. Mais vous pouvez toujours vous construire dans une réentrance logique : un CPI qui lit votre état, puis votre code le relit en supposant que le CPI ne l’a pas changé. Pour Raydium, les CPI ne touchent pas votre état, donc c’est moins une préoccupation que p. ex. les contextes de prêt-éclair. Mais si vous composez Raydium avec un protocole de prêt, soyez conscient.Dérive de mutabilité de compte
Si votre programme passe un compte commemut mais Raydium l’attend en lecture seule (ou vice versa), l’exécution rejette l’invocation avec InvalidAccountData. Vérifiez toujours la mutabilité attendue de l’instruction Raydium dans l’IDL ; anchor_cp_swap::cpi::accounts::Swap l’applique via ses types de champ.
Champ du programme Token-2022
Les mints d’entrée et de sortie peuvent être sous différents programmes de token — un Token SPL, un Token-2022. Le CPI a des champsinput_token_program et output_token_program séparés pour cette raison. Vérifiez toujours le champ owner de chaque mint et routez le programme correct dans chaque slot.
Transactions versionnées
Une transaction composée qui fait 2+ CPI Raydium plus une création ATA s’adapte rarement dans une transaction héritée (v0-sans-LUT). Utilisez V0 avec les tables de consultation d’adresses ; tirez les LUT publiques de Raydium viaraydium.getRaydiumLutAddresses().
Pointeurs
sdk-api/rust-cpi— mécanique CPI bas niveau.integration-guides/priority-fee-tuning— dimensionnement du budget de calcul.products/cpmm/code-demos,products/clmm/code-demos,products/farm-staking/code-demos— extraits CPI par produit.

