Acceso a Cuentas
Usa ctx.accounts para campos tipados, ctx.bumps para semillas de PDA, y ctx.remaining_accounts para listas de cuentas variables pasadas después del layout fijo.
Receta
pub fn route(ctx: Context<Route>) -> Result<()> {
let bump = ctx.bumps.vault;
let vault = &mut ctx.accounts.vault;
for acc in ctx.remaining_accounts.iter() {
require!(acc.owner == &crate::ID, MyError::BadRemaining);
}
Ok(())
}Cuándo usar esto: Los manejadores leen o mutan cuentas validadas y extras opcionales.
Ejemplo Funcional
pub fn swap(ctx: Context<Swap>) -> Result<()> {
let user = &ctx.accounts.user;
let pool = &mut ctx.accounts.pool;
let bump = ctx.bumps.pool;
msg!("user: {}, pool bump: {}", user.key(), bump);
for meta in ctx.remaining_accounts.iter() {
let ai = meta.to_account_info();
require!(ai.is_writable, SwapError::ReadonlyAccount);
}
Ok(())
}Qué demuestra esto:
- Los campos de cuenta son referencias con tiempos de vida ligados al Contexto
ctx.bumps.<nombre>coincide con el nombre del campo de semillasremaining_accountses un slice de AccountInfo- Usa
to_account_info()para metadatos de cuenta de CPI
Análisis Profundo
Mutación de Cuentas
&mut Account<'info, T> serializa los cambios al final de la instrucción si la cuenta fue marcada como mut en las restricciones.
remaining_accounts
Los clientes añaden cuentas después del orden del IDL. Documenta el orden esperado y valida cada entrada.
Errores Comunes
- remaining_accounts no validado - Vulnerabilidad crítica. Solución: Comprueba el propietario, discriminador, firmante según sea necesario.
- Nombre de bump incorrecto en ctx.bumps - El nombre del campo debe coincidir con el campo de cuenta de semillas. Solución: Usa el nombre exacto del campo de la struct.
- Clonación innecesaria de AccountInfo - Desperdicio de CU. Solución: Pasa referencias a las funciones auxiliares de CPI.
- Asumir el orden de remaining del IDL - Solo las cuentas fijas están en el IDL. Solución: Publica documentación separada para los extras.
- Lectura de datos antes de la validación en otro crate - Solo se aplica a rutas no verificadas. Solución: Mantén la validación primero en las restricciones.
Alternativas
| Alternativa | Usar Cuándo | No Usar Cuándo |
|---|---|---|
| Vec explícito de cuentas en struct | Conjuntos pequeños y fijos | Enrutamiento dinámico grande |
| AccountLoader::load | Lecturas sin copia | Account<T> estándar |
| Cuentas Sysvar en struct | Clock, rent | remaining_accounts para sysvars raras |
Preguntas Frecuentes
¿Qué versión de Anchor se asume?
0.32.1 en toda esta sección.
¿Puede un PDA ser un Signer en la struct de cuentas?
No. Usa restricciones de semillas y firma de CPI.
¿Dónde se almacena el bump?
En el campo de tu struct de cuenta, establecido al inicializar.
¿Cómo derivan los clientes los PDA?
Usa @solana/kit 7.0.0 con bytes de semilla coincidentes.
¿Qué ID de programa se usa para los PDA?
La dirección declare_id de tu programa Anchor.
¿Incluyen las semillas el bump?
No en el array de semillas; el bump es un parámetro separado para find_program_address.
¿Cómo depurar fallos de PDA?
Compara las claves registradas; verifica las semillas y el ID del programa en el lado del cliente.
¿Son los PDA exentos de rent?
Sí, cuando contienen datos; financia con el pagador al inicializar.
¿Puede un PDA firmar múltiples CPI en una ix?
Sí, con las mismas semillas de firmante para cada CPI.
¿Qué leer a continuación?
Consulta los enlaces relacionados para temas más profundos sobre acceso.
Relacionado
- remaining_accounts - conjuntos dinámicos
- Pasar Cuentas Restantes - extras de CPI
- Manejadores de Instrucciones - Resumen del Contexto
Versiones de Stack: 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.