Esta página fue traducida automáticamente por IA. La versión en inglés es la fuente autorizada.Ver versión en inglés →
PDAs (direcciones derivadas de programas) y CPIs (invocaciones entre programas) son los dos primitivos que hacen posible Raydium. Los PDAs permiten que un programa “posea” direcciones deterministas sin claves privadas — así es como funcionan las autoridades de pools y las bóvedas. Los CPIs permiten que un programa llame a otro — así es como Raydium intercambia tokens a través del programa SPL Token y cómo los integradores componen Raydium en sus propios flujos. Ambos merecen ser entendidos antes de leer el código fuente de Raydium.
PDAs: direcciones sin claves
Una Dirección Derivada de Programa es una clave pública que:- No está en la curva ed25519 (no existe clave privada para ella).
- Se deriva de forma determinista a partir de un ID de programa y un conjunto de seeds.
- Solo puede ser firmada por el programa de derivación, mediante
invoke_signed.
Derivación
Un PDA se calcula hasheando el ID del programa con los seeds, luego encontrando un byte “bump” que fuerza el resultado fuera de la curva. El primer bump (típicamente comenzando desde 255 y decrementando) que produce una dirección fuera de la curva gana; este es el bump canónico.u64 como bytes little-endian. La convención de Raydium es un prefijo legible por humanos seguido de identificadores únicos.
Patrones de PDA en Raydium
PDAs comunes en los programas de Raydium:
Los usuarios e integradores pueden calcular estos sin obtener nada — dados los inputs públicos (ID de pool, ID de granja, clave de usuario), el PDA es determinista.
Bump canónico
Aunque en principio puede haber múltiples bumps que produzcan direcciones fuera de la curva, los programas de Raydium siempre usan el bump canónico (encontrado decrementando desde 255). Este se almacena en los datos de la cuenta del PDA para que las transacciones posteriores puedan pasarlo y omitir el bucle de derivación (costoso):PoolState de CLMM almacena bump: [u8; 1] en su lugar, así que verifica la struct del programa específico en lugar de asumir una forma.)
En transacciones posteriores, el bump se lee del estado del pool en lugar de ser recomputado.
CPIs: llamar a otros programas
Invocación Entre Programas permite que un programa invoque las instrucciones de otro programa en línea dentro de una única transacción. Raydium usa CPIs extensamente:- Las instrucciones de swap llaman al programa SPL Token para mover tokens.
- CLMM llama a Metaplex para acuñar el NFT de posición.
- La creación de pool llama al Programa del Sistema para asignar cuentas.
- Farm v6 llama a SPL Token para transferir recompensas.
integration-guides/cpi-integration.
invoke vs invoke_signed
El runtime de Solana ofrece dos primitivos de CPI:invoke: llamar a otro programa; el programa llamado hereda los firmantes de la transacción externa.invoke_signed: llamar a otro programa en nombre de un PDA; el runtime verifica los seeds del PDA y autoriza la firma.
invoke_signed es la magia que permite que los programas tengan autoridad sobre cuentas sin gestionar claves privadas.
Ejemplo: Raydium transfiriendo desde una bóveda de pool
Una bóveda de pool es una Cuenta de Token cuya autoridad es un PDA del programa de pool. Para transferir tokens durante un swap, el programa de pool debe firmar como ese PDA:invoke_signed es llamado por el programa CPMM, verifica que vault_and_lp_mint_auth_seed + bump se derive a la dirección de pool_authority cuando se hashea con el ID del programa CPMM, y permite la firma de autoridad en la transferencia de token. Sin clave privada involucrada.
Ejemplo: integrador llamando a Raydium CPMM
Un programa integrador (por ejemplo, un escrow) puede invocarswap_base_input de Raydium mediante CPI:
integration-guides/cpi-integration para el ejemplo completo de escrow.
Límite de profundidad de CPI
Solana limita la profundidad de CPI a 4 niveles. La instrucción de nivel superior de una transacción cuenta como profundidad 0; cada invocación de CPI incrementa la profundidad. Implicación práctica: el propio swap de Raydium ya usa 1-2 niveles de CPI (Raydium → SPL Token). Un integrador que llama a Raydium usa 2. Si ese integrador es llamado por otro integrador, es 3. El 4º nivel es el límite. La mayoría de las composiciones se mantienen por debajo de esto fácilmente, pero el anidamiento profundo (agregador → router → Raydium → hook) puede alcanzarlo. Diseña de forma plana en lugar de profunda.Cuentas restantes
Cuando una instrucción de Raydium necesita un número variable de cuentas (por ejemplo, un swap de CLMM cruzando un número desconocido de arrays de tick), las cuentas adicionales se pasan como cuentas restantes — anexadas a la lista de cuentas fijas, interpretadas por posición. ElSwapV2 de CPMM usa cuentas restantes para las cuentas adicionales requeridas de los programas de transfer-hook. Los clientes obtienen las cuentas necesarias y las anexan:
Trampas de PDA
Seeds incorrectos → dirección incorrecta
Un bug donde los seeds están en el orden incorrecto, codificación incorrecta, o incluyen/excluyen un byte adicional produce silenciosamente un PDA diferente. La transacción falla de forma ambigua (el programa intenta leer una cuenta que no existe). Siempre prueba unitariamente la derivación de seeds contra valores dorados conocidos.No almacenar bump
Si re-derives el bump en cada transacción, pagas compute por el bucle de derivación. Almacena el bump canónico en los datos del PDA y léelo desde allí.Confundir bump canónico vs no canónico
Los bumps no canónicos (si alguien encuentra uno que produce fuera de la curva) son permitidos porinvoke_signed pero rechazados por los programas de Raydium mediante assert_eq!(bump, canonical_bump). Si alguien intenta reclamar un PDA con un bump no canónico, la tx falla.
Pasar un PDA como firmante cuando no eres el programa propietario
Solo el programa cuyo ID está en la derivación del PDA puedeinvoke_signed con sus seeds. Si lo intentas, el runtime lo rechaza.
Trampas de CPI
Olvidar reenviar remaining_accounts
Si tu instrucción externa pasa cuentas de transfer-hook en remaining_accounts pero el CPI hacia Raydium no las reenvía, Raydium falla porque no puede encontrar las cuentas de hook. Siempre incluye with_remaining_accounts en CPIs que lo necesiten.
Desajuste de flags escribibles
Una cuenta que la instrucción externa marca como escribible también debe ser escribible en la llamada de CPI si el programa llamado intenta escribirla. Desajuste → rechazo del runtime.No contabilizar renta
CPI a un programa que crea una cuenta (por ejemplo, creación de ATA) requiere que el pagador tenga suficiente SOL para renta. Las verificaciones de renta fallidas aparecen como errores oscuros.Ejemplo trabajado: calculando PDAs de CPMM de Raydium
getPoolInfoFromRpc({ poolId }) — deriva los PDAs asociados sin un viaje de ida y vuelta.
Referencias
solana-fundamentals/account-model— cómo los PDAs encajan en el modelo de cuentas.solana-fundamentals/programs-and-anchor— los helpers de Anchor para declarar PDAs.integration-guides/cpi-integration— construir integraciones que hagan CPI hacia Raydium.sdk-api/rust-cpi— tipos de CPI de Rust de Raydium.
- Documentos de PDA de Solana.
- Documentos de CPI de Solana.
- Documentos de PDA de Anchor y Documentos de CPI de Anchor — Anchor no tiene una página combinada.

