Esta página foi traduzida automaticamente por IA. A versão em inglês é a fonte oficial.Ver versão em inglês →
PDAs (endereços derivados de programa) e CPIs (invocação entre programas) 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 de Raydium.
PDAs: endereços sem chaves
Um Endereço Derivado de Programa é uma chave pública que:- Não está na curva ed25519 (nenhuma chave privada existe para ela).
- É derivada deterministicamente 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 fazendo 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 (tipicamente começando de 255 e decrementando) que produz um endereço fora da curva vence; este é o bump canônico.u64 como bytes little-endian. A convenção de Raydium é um prefixo legível por humanos seguido de identificadores únicos.
Padrões de PDA em Raydium
PDAs comuns nos programas de Raydium:
Usuários e integradores podem calcular esses PDAs sem buscar nada — dados os inputs públicos (ID do pool, ID do farm, chave do usuário), o PDA é determinístico.
Bump canônico
Embora em princípio possa haver múltiplos bumps produzindo endereços fora da curva, os programas de Raydium sempre usam o bump canônico (encontrado decrementando de 255). Isso é armazenado nos dados da conta PDA para que transações subsequentes possam passá-lo e pular o loop de derivação (caro):PoolState de CLMM armazena bump: [u8; 1] em vez disso, então verifique a struct do programa específico em vez de assumir uma forma.)
Em transações subsequentes, o bump é lido do estado do pool em vez de ser recalculado.
CPIs: chamando outros programas
Invocação Entre Programas 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 o NFT de posição.
- 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 runtime de Solana oferece dois primitivos de CPI:invoke: chama outro programa; o programa chamado herda os signatários da transação externa.invoke_signed: chama outro programa em nome de um PDA; o runtime 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 Conta de Token cuja autoridade é um PDA do programa de pool. Para transferir tokens durante um swap, o programa de 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 CPMM de Raydium
Um programa integrador (por exemplo, um escrow) pode invocarswap_base_input de 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 de CPI incrementa a profundidade. Implicação prática: o próprio swap de 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 bem abaixo disso, mas aninhamento profundo (agregador → roteador → Raydium → hook) pode atingir. Projete de forma plana em vez de profunda.Contas restantes
Quando uma instrução de Raydium precisa de um número variável de contas (por exemplo, swap de CLMM cruzando um número desconhecido de arrays de tick), as contas extras são passadas como contas restantes — anexadas à lista de contas fixas, interpretadas por posição. OSwapV2 de CPMM usa contas restantes para 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 faça testes unitários de derivação de seed contra valores golden conhecidos.Não armazenar bump
Se você re-derivar o bump em cada transação, você paga computação pelo loop de derivação. Armazene o bump canônico nos dados do PDA e leia-o de lá.Confundindo bump canônico vs não-canônico
Bumps não-canônicos (se alguém encontrar um que produza fora da curva) são permitidos porinvoke_signed mas rejeitados pelos programas de Raydium via assert_eq!(bump, canonical_bump). Se alguém tentar reivindicar um PDA com um bump não-canônico, a tx falha.
Passando 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 você tentar, o runtime rejeita.
Armadilhas de CPI
Esquecendo de encaminhar remaining_accounts
Se sua instrução externa passa contas de transfer-hook em remaining_accounts mas o CPI para Raydium não as encaminha, Raydium falha porque não consegue encontrar as contas de hook. Sempre inclua with_remaining_accounts em CPIs que precisam delas.
Incompatibilidade de flags graváveis
Uma conta que a instrução externa marca como gravável também deve ser gravável na chamada de CPI se o programa chamado pretende escrevê-la. Incompatibilidade → rejeição do runtime.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 trabalhado: computando PDAs de CPMM de Raydium
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 de Anchor para declarar PDAs.integration-guides/cpi-integration— construindo integrações que CPI para Raydium.sdk-api/rust-cpi— tipos de CPI Rust de Raydium.
- Documentação de PDA de Solana.
- Documentação de CPI de Solana.
- Documentação de PDA de Anchor e Documentação de CPI de Anchor — Anchor não tem uma página combinada.

