Passando Contas Restantes
Encaminhe remaining_accounts para CPIs quando o chamado espera listas de contas variáveis (roteamento, oráculos, trocas multi-hop).
Receita
let mut cpi_ctx = CpiContext::new(program, accounts);
cpi_ctx = cpi_ctx.with_remaining_accounts(
ctx.remaining_accounts.iter().map(|a| a.to_account_info()).collect(),
);Quando usar isso: O programa chamado documenta contas além do seu layout fixo de IDL.
Exemplo Funcional
pub fn relay(ctx: Context<Relay>) -> Result<()> {
for acc in ctx.remaining_accounts.iter() {
require!(acc.owner == &expected_owner, RelayError::BadAccount);
}
let mut cpi_ctx = CpiContext::new(
ctx.accounts.target_program.to_account_info(),
target::cpi::accounts::Handle { admin: ctx.accounts.admin.to_account_info() },
);
cpi_ctx = cpi_ctx.with_remaining_accounts(ctx.remaining_accounts.to_vec());
target::cpi::handle(cpi_ctx)?;
Ok(())
}O que isso demonstra:
- Valide cada conta restante antes da CPI
- A ordem deve corresponder às expectativas do chamado
- Combine com structs de CPI
declare_program - Documente o formato de roteamento para clientes
Análise Detalhada
Responsabilidade do Cliente
Clientes anexam contas após as contas fixas da IDL nas metadados da transação. Incompatibilidade causa falha do chamado ou bugs de segurança.
Impacto de CU
Iterar grandes conjuntos restantes consome CU; limite a contagem com require!(len <= MAX).
Armadilhas
- Contas restantes não validadas - Vulnerabilidade crítica. Correção: Verifique o proprietário, signatário, discriminador.
- Ordem incorreta encaminhada - O chamado lê a conta errada como oráculo. Correção: Publique uma especificação de ordenação rigorosa.
- Comprimento ilimitado - Exaustão de CU. Correção: Aplique a contagem máxima de contas restantes.
- Mistura de contas restantes com inicialização - Confusão de ordenação do Anchor. Correção: Mantenha contas fixas apenas na struct.
- Assumir que o chamado valida o mesmo que você - Falta de defesa em profundidade. Correção: Valide em ambos os lados.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Struct de conta fixa | Layout conhecido | Roteadores dinâmicos |
| Metadados de conta nos dados da instrução | Padrões raros | remaining_accounts padrão |
FAQs
Formato de erro do Anchor 0.32.1?
Códigos personalizados na IDL mais strings #[msg].
emit! vs emit_cpi!?
emit_cpi! custa mais CU, mas melhora a confiabilidade da captura.
Devo usar msg! na mainnet?
Evite, exceto atrás de flags de recursos.
Como os clientes obtêm códigos de erro?
Da IDL via Anchor ou geração de código Codama.
Eventos aparecem na IDL?
Sim, tipos #[event] são listados.
Restrições podem retornar erros personalizados?
Sim, com @MyError::Variant.
O que usa CU em logging?
Cada linha de log e string formatada.
Como testar erros?
anchor test esperando códigos de erro.
Logs são dados de consenso?
Sim, mas não um contrato de API; use eventos.
Próxima leitura?
Veja Relacionados para CPIs restantes.
Relacionados
- remaining_accounts - lado do programa
- Acessando Contas -
ctx.remaining_accounts - Segurança de CPI - validação
Versões da Stack: Esta página foi escrita para Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, e LiteSVM 0.6.x.