Pasar Cuentas Restantes
Pasa remaining_accounts a las CPIs cuando el programa llamado espera listas de cuentas variables (enrutamiento, oráculos, swaps de múltiples saltos).
Receta
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(),
);Cuándo usar esto: El programa llamado documenta cuentas más allá de su diseño fijo de IDL.
Ejemplo 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(())
}Lo que esto demuestra:
- Validar cada cuenta restante antes de la CPI.
- El orden debe coincidir con las expectativas del programa llamado.
- Combinar con las estructuras CPI
declare_program. - Documentar el formato de enrutamiento para los clientes.
Análisis Profundo
Responsabilidad del Cliente
Los clientes añaden cuentas después de las cuentas fijas de la IDL en las metadatos de la transacción. Un desajuste causa fallos en el programa llamado o errores de seguridad.
Impacto de CU
Iterar sobre grandes conjuntos restantes cuesta CU; limita el número con require!(len <= MAX).
Trampas Comunes
- Cuentas restantes no validadas - Vulnerabilidad crítica. Solución: Comprobar propietario, firmante, discriminador.
- Orden incorrecto al pasar - El programa llamado lee la cuenta incorrecta como oráculo. Solución: Publicar una especificación de orden estricta.
- Longitud ilimitada - Agotamiento de CU. Solución: Forzar un número máximo de cuentas restantes.
- Mezclar cuentas restantes con inicialización - Confusión en el orden de Anchor. Solución: Mantener las cuentas fijas solo en la estructura.
- Asumir que el programa llamado valida lo mismo que tú - Falta de defensa en profundidad. Solución: Validar en ambos lados.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| Estructura de cuenta fija | Diseño conocido | Enrutadores dinámicos |
| Metadatos de cuenta en datos de instrucción | Patrones raros | remaining_accounts estándar |
Preguntas Frecuentes
¿Formato de error de Anchor 0.32.1?
Códigos personalizados en la IDL más cadenas #[msg].
¿emit! vs emit_cpi!?
emit_cpi! cuesta más CU pero mejora la fiabilidad de la captura.
¿Debería usar msg! en mainnet?
Evitar excepto detrás de indicadores de características.
¿Cómo obtienen los clientes los códigos de error?
Desde la IDL a través de la generación de código de Anchor o Codama.
¿Aparecen los eventos en la IDL?
Sí, los tipos #[event] están listados.
¿Pueden las restricciones devolver errores personalizados?
Sí, con @ MyError::Variant.
¿Qué usa CU en el registro?
Cada línea de registro y cadena formateada.
¿Cómo probar errores?
anchor test esperando códigos de error.
¿Son los registros datos de consenso?
Sí, pero no un contrato de API; usar eventos.
¿Próxima lectura?
Ver Relacionados para CPIs restantes.
Relacionados
- remaining_accounts - lado del programa
- Accediendo a Cuentas -
ctx.remaining_accounts - Seguridad de CPI - validación
Versiones de la pila: Esta página fue 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, y LiteSVM 0.6.x.