Cette page est traduite automatiquement par IA. La version anglaise fait foi.Voir la version anglaise →
Les PDAs (adresses dérivées de programme) et les CPIs (invocations inter-programme) sont les deux primitives qui rendent Raydium possible. Les PDAs permettent à un programme de « posséder » des adresses déterministes sans clés privées — c’est ainsi que fonctionnent les autorités de pool et les coffres. Les CPIs permettent à un programme d’appeler un autre — c’est ainsi que Raydium échange des tokens via le programme SPL Token et comment les intégrateurs composent Raydium dans leurs propres flux. Il vaut la peine de comprendre les deux avant de lire le code source de Raydium.
PDAs : des adresses sans clés
Une adresse dérivée de programme est une clé publique qui :- N’est pas sur la courbe ed25519 (aucune clé privée n’existe pour elle).
- Est dérivée de manière déterministe à partir d’un ID de programme et d’un ensemble de seeds.
- Ne peut être signée que par le programme de dérivation, via
invoke_signed.
Dérivation
Un PDA est calculé en hachant l’ID du programme avec les seeds, puis en trouvant un octet « bump » qui force le résultat hors de la courbe. Le premier bump (généralement en commençant par 255 et en décrémentant) qui produit une adresse hors-courbe gagne ; c’est le bump canonique.u64 en octets little-endian. La convention de Raydium est un préfixe lisible par l’homme suivi d’identifiants uniques.
Motifs PDA de Raydium
Les PDAs courants dans les programmes de Raydium :
Les utilisateurs et les intégrateurs peuvent calculer ces PDAs sans rien récupérer — étant donné les entrées publiques (ID du pool, ID de la farm, clé utilisateur), le PDA est déterministe.
Bump canonique
Bien qu’il puisse en principe y avoir plusieurs bumps produisant des adresses hors-courbe, les programmes de Raydium utilisent toujours le bump canonique (trouvé en décrémentant à partir de 255). Celui-ci est stocké dans les données du compte PDA afin que les transactions ultérieures puissent le passer et ignorer la boucle de dérivation (coûteuse) :PoolState de CLMM stocke bump: [u8; 1] à la place, donc vérifiez la struct du programme spécifique plutôt que d’assumer une forme unique.)
Lors des transactions ultérieures, le bump est lu à partir de l’état du pool plutôt que recalculé.
CPIs : appeler d’autres programmes
L’invocation inter-programme permet à un programme d’invoquer les instructions d’un autre programme en ligne dans une seule transaction. Raydium utilise les CPIs de manière extensive :- Les instructions de swap appellent le programme SPL Token pour déplacer les tokens.
- CLMM appelle Metaplex pour frapper le NFT de position.
- La création de pool appelle le System Program pour allouer des comptes.
- Farm v6 appelle SPL Token pour transférer les récompenses.
integration-guides/cpi-integration.
invoke vs invoke_signed
Le runtime Solana offre deux primitives CPI :invoke: appeler un autre programme ; le programme appelé hérite des signataires de la transaction externe.invoke_signed: appeler un autre programme au nom d’un PDA ; le runtime vérifie les seeds du PDA et autorise la signature.
invoke_signed est la magie qui permet aux programmes de détenir l’autorité sur les comptes sans gérer les clés privées.
Exemple : Raydium transférant depuis un coffre de pool
Un coffre de pool est un Token Account dont l’autorité est un PDA du programme de pool. Pour transférer des tokens lors d’un swap, le programme de pool doit signer en tant que ce PDA :invoke_signed est appelé par le programme CPMM, vérifie que vault_and_lp_mint_auth_seed + bump dérive vers l’adresse de pool_authority lorsqu’il est haché avec l’ID du programme CPMM, et autorise la signature de l’autorité sur le transfert de token. Aucune clé privée impliquée.
Exemple : intégrateur appelant Raydium CPMM
Un programme intégrateur (par exemple, un escrow) peut invoquerswap_base_input de Raydium via CPI :
integration-guides/cpi-integration pour l’exemple complet d’escrow.
Limite de profondeur CPI
Solana plafonne la profondeur CPI à 4 niveaux. L’instruction de niveau supérieur d’une transaction compte comme profondeur 0 ; chaque invocation CPI incrémente la profondeur. Implication pratique : le propre swap de Raydium utilise déjà 1-2 niveaux de CPI (Raydium → SPL Token). Un intégrateur appelant Raydium en utilise 2. Si cet intégrateur est appelé par un autre intégrateur, c’est 3. Le 4e niveau est la limite. La plupart des compositions restent bien en dessous de cela, mais l’imbrication profonde (agrégateur → routeur → Raydium → hook) peut l’atteindre. Concevez de manière plate plutôt que profonde.Comptes restants
Lorsqu’une instruction Raydium a besoin d’un nombre variable de comptes (par exemple, un swap CLMM traversant un nombre inconnu de tableaux de ticks), les comptes supplémentaires sont passés en tant que comptes restants — ajoutés à la liste des comptes fixes, interprétés par position. LeSwapV2 de CPMM utilise les comptes restants pour les comptes supplémentaires requis des programmes de transfer-hook. Les clients récupèrent les comptes nécessaires et les ajoutent :
Pièges des PDAs
Mauvaises seeds → mauvaise adresse
Un bug où les seeds sont dans le mauvais ordre, mauvais encodage, ou incluent/excluent un octet supplémentaire produit silencieusement un PDA différent. La transaction échoue de manière ambiguë (le programme essaie de lire un compte qui n’existe pas). Testez toujours unitairement la dérivation des seeds par rapport à des valeurs de référence connues.Ne pas stocker le bump
Si vous redérivez le bump à chaque transaction, vous payez du calcul pour la boucle de dérivation. Stockez le bump canonique dans les données du PDA et lisez-le à partir de là.Confondre bump canonique vs non-canonique
Les bumps non-canoniques (si quelqu’un en trouve un qui produit hors-courbe) sont autorisés parinvoke_signed mais rejetés par les programmes de Raydium via assert_eq!(bump, canonical_bump). Si quelqu’un essaie de réclamer un PDA avec un bump non-canonique, la tx échoue.
Passer un PDA en tant que signataire quand vous n’êtes pas le programme propriétaire
Seul le programme dont l’ID est dans la dérivation du PDA peutinvoke_signed avec ses seeds. Si vous essayez, le runtime rejette.
Pièges des CPIs
Oublier de transférer remaining_accounts
Si votre instruction externe passe les comptes de transfer-hook dans remaining_accounts mais que le CPI dans Raydium ne les transfère pas, Raydium échoue car il ne peut pas trouver les comptes de hook. Incluez toujours with_remaining_accounts dans les CPIs qui en ont besoin.
Désaccord des drapeaux writable
Un compte que l’instruction externe marque comme writable doit également être writable dans l’appel CPI si le programme appelé a l’intention de l’écrire. Désaccord → rejet du runtime.Ne pas tenir compte de la rente
CPI vers un programme qui crée un compte (par exemple, création d’ATA) nécessite que le payeur ait suffisamment de SOL pour la rente. Les vérifications de rente échouées apparaissent comme des erreurs obscures.Exemple travaillé : calcul des PDAs CPMM de Raydium
getPoolInfoFromRpc({ poolId }) — il dérive les PDAs associés sans aller-retour.
Pointeurs
solana-fundamentals/account-model— comment les PDAs s’intègrent dans le modèle de compte.solana-fundamentals/programs-and-anchor— les aides d’Anchor pour déclarer les PDAs.integration-guides/cpi-integration— construire des intégrations qui font des CPIs dans Raydium.sdk-api/rust-cpi— les types Rust CPI de Raydium.
- Docs PDA Solana.
- Docs CPI Solana.
- Docs PDA Anchor et Docs CPI Anchor — Anchor n’a pas de page combinée.

