Documentation Index
Fetch the complete documentation index at: https://docs.raydium.io/llms.txt
Use this file to discover all available pages before exploring further.
Esta página foi traduzida automaticamente por IA. A versão em inglês é a fonte oficial.Ver versão em inglês →
PDAs (program-derived addresses) e CPIs (cross-program invocation) são os dois primitivos que tornam Raydium possível. PDAs permitem que um programa “possua” endereços determinísticos sem chaves privadas — é assim que as autoridades de pool e vaults funcionam. CPIs permitem que um programa chame outro — é assim que Raydium troca tokens via o programa SPL Token e como integradores compõem Raydium em seus próprios fluxos. Ambos valem a pena entender antes de ler o código-fonte do Raydium.
PDAs: endereços sem chaves
Um Program-Derived Address é uma chave pública que:- Não está na curva ed25519 (nenhuma chave privada existe para ela).
- É derivada de forma determinística a partir de um ID de programa e um conjunto de seeds.
- Pode ser assinada apenas pelo programa de derivação, via
invoke_signed.
Derivação
Um PDA é calculado ao fazer o hash do ID do programa com as seeds, depois encontrando um byte “bump” que força o resultado para fora da curva. O primeiro bump (normalmente começando de 255 e decrementando) que produz um endereço fora da curva vence; este é o canonical bump.u64 como bytes little-endian. A convenção Raydium é um prefixo legível seguido de identificadores únicos.
Padrões de PDA no Raydium
PDAs comuns nos programas Raydium:| PDA | Seeds | Programa |
|---|---|---|
| AMM authority (AMM v4) | [b"amm authority"] + bump | AMM v4 |
| Pool state (CPMM) | [b"pool", amm_config, mint_a, mint_b] | CPMM |
| Pool vault (CPMM) | [b"pool_vault", pool, mint] | CPMM |
| Authority (CPMM) | [b"vault_and_lp_mint_auth_seed"] | CPMM |
| Pool state (CLMM) | [b"pool", amm_config, mint_0, mint_1] | CLMM |
| Tick array (CLMM) | [b"tick_array", pool, start_tick_index] | CLMM |
| Observation (CLMM) | [b"observation", pool] | CLMM |
| Personal position (CLMM) | [b"position", position_nft_mint] | CLMM |
| Farm state (Farm v6) | [b"pool_farm_state", farm_id] | Farm v6 |
| User ledger (Farm v6) | [b"user_ledger", farm, user] | Farm v6 |
Canonical bump
Embora em princípio possa haver múltiplos bumps produzindo endereços fora da curva, os programas Raydium sempre usam o canonical bump (encontrado ao decrementar de 255). Este é armazenado nos dados da conta PDA para que transações subsequentes possam passá-lo e pular o loop de derivação (caro):CPIs: chamando outros programas
Cross-Program Invocation permite que um programa invoque as instruções de outro programa inline dentro de uma única transação. Raydium usa CPIs extensivamente:- Instruções de swap chamam o programa SPL Token para mover tokens.
- CLMM chama Metaplex para cunhar a posição NFT.
- Criação de pool chama System Program para alocar contas.
- Farm v6 chama SPL Token para transferir recompensas.
integration-guides/cpi-integration.
invoke vs invoke_signed
O tempo de execução Solana oferece dois primitivos CPI:invoke: chama outro programa; o programa chamado herda os signers da transação externa.invoke_signed: chama outro programa em nome de um PDA; o tempo de execução verifica as seeds do PDA e autoriza a assinatura.
invoke_signed é a mágica que permite que programas mantenham autoridade sobre contas sem gerenciar chaves privadas.
Exemplo: Raydium transferindo de um vault de pool
Um vault de pool é uma Token Account cuja autoridade é um PDA do programa do pool. Para transferir tokens durante um swap, o programa do pool deve assinar como esse PDA:invoke_signed é chamado pelo programa CPMM, verifica que vault_and_lp_mint_auth_seed + bump deriva para o endereço de pool_authority quando feito hash com o ID do programa CPMM, e permite a assinatura de autoridade na transferência de token. Nenhuma chave privada envolvida.
Exemplo: integrador chamando Raydium CPMM
Um programa integrador (por exemplo, um escrow) pode invocarswap_base_input do Raydium via CPI:
integration-guides/cpi-integration para o exemplo completo de escrow.
Limite de profundidade de CPI
Solana limita a profundidade de CPI a 4 níveis. A instrução de nível superior de uma transação conta como profundidade 0; cada invocação CPI incrementa a profundidade. Implicação prática: o próprio swap Raydium já usa 1-2 níveis de CPI (Raydium → SPL Token). Um integrador chamando Raydium usa 2. Se esse integrador é chamado por outro integrador, é 3. O 4º nível é o limite. A maioria das composições fica abaixo disso facilmente, mas aninhamento profundo (agregador → roteador → Raydium → hook) pode atingir. Projete plano em vez de profundo.Contas restantes
Quando uma instrução Raydium precisa de um número variável de contas (por exemplo, swap CLMM cruzando um número desconhecido de tick arrays), as contas extras são passadas como remaining accounts — anexadas à lista de contas fixas, interpretadas por posição.SwapV2 da CPMM usa remaining accounts para as contas extras necessárias dos programas de transfer-hook. Clientes buscam as contas necessárias e as anexam:
Armadilhas de PDA
Seeds erradas → endereço errado
Um bug onde as seeds estão na ordem errada, codificação errada, ou incluem/excluem um byte extra produz silenciosamente um PDA diferente. A transação falha de forma ambígua (o programa tenta ler uma conta que não existe). Sempre teste unitariamente a derivação de seed contra valores ouro conhecidos.Não armazenar bump
Se você derivar novamente o bump em cada transação, você paga computação para o loop de derivação. Armazene o canonical bump nos dados do PDA e leia de lá.Confundindo canonical vs non-canonical bump
Bumps não-canônicos (se alguém encontrar um que produza fora da curva) são permitidos porinvoke_signed mas rejeitados pelos programas Raydium via assert_eq!(bump, canonical_bump). Se alguém tentar reivindicar um PDA com um bump não-canônico, a tx falha.
Passar um PDA como signatário quando você não é o programa proprietário
Apenas o programa cujo ID está na derivação do PDA podeinvoke_signed com suas seeds. Se tentar, o tempo de execução rejeita.
Armadilhas de CPI
Esquecendo de repassar remaining_accounts
Se sua instrução externa passa contas de transfer-hook em remaining_accounts mas o CPI para Raydium não as repassa, Raydium falha porque não consegue encontrar as contas de hook. Sempre inclua with_remaining_accounts em CPIs que precisam delas.
Desajuste de flags graváveis
Uma conta que a instrução externa marca como gravável também deve ser gravável na chamada CPI se o programa chamado pretende escrever nela. Desajuste → rejeição do tempo de execução.Não contabilizar aluguel
CPI para um programa que cria uma conta (por exemplo, criação de ATA) requer que o pagador tenha SOL suficiente para aluguel. Verificações de aluguel falhadas aparecem como erros obscuros.Exemplo prático: calculando PDAs Raydium CPMM
getPoolInfoFromRpc({ poolId }) — ele deriva os PDAs associados sem uma viagem de ida e volta.
Referências
solana-fundamentals/account-model— como PDAs se encaixam no modelo de conta.solana-fundamentals/programs-and-anchor— helpers do Anchor para declarar PDAs.integration-guides/cpi-integration— construindo integrações que CPI para Raydium.sdk-api/rust-cpi— tipos Rust CPI do Raydium.


