Pasar Cuentas a CPIs
Las listas de cuentas de CPI deben reflejar el orden esperado del llamado, las banderas de firmante y la capacidad de escritura. Tu programa es responsable de no elevar privilegios más allá de lo que la transacción externa pretendía.
Receta
let metas = vec![
AccountMeta::new(source, false),
AccountMeta::new(dest, false),
AccountMeta::new_readonly(authority, true),
];Cuándo usar esto:
- Al construir CPIs personalizadas a programas SPL.
- Al auditar la escalada de privilegios.
- Al componer múltiples CPIs en una sola instrucción.
Ejemplo Funcional
// Validar que la fuente sea escribible solo si el llamador pretendía una mutación
if !source.is_writable { return Err(ProgramError::InvalidAccountData); }
let ix = spl_token::instruction::transfer(...)?;
invoke(&ix, &[source.clone(), dest.clone(), authority.clone(), token_program.clone()])?;Lo que esto demuestra:
- Verificación explícita de escritura antes de la CPI.
- Autoridad marcada como firmante en las metadatos.
- Incluida la cuenta del programa de tokens.
Análisis Profundo
Escalada de Privilegios
Pasar writable + signer al llamado cuando la transacción externa no lo autorizó es un error crítico.
Ordenamiento
Sigue las definiciones de origen del llamado (spl-token, system).
Notas de Rust
// AccountMeta::new_readonly(key, is_signer)Trampas Comunes
- Cuentas escribibles adicionales - El llamado muta la cuenta del atacante. Solución: Metadatos de mínimo privilegio.
- Cuenta de programa faltante - La CPI falla. Solución: Incluir la cuenta del ID del programa del llamado.
- Escalada de firmante - Marcar una cuenta no firmante como firmante. Solución: Coincidir con las banderas de la transacción externa, a menos que sea una PDA.
- Intercambio de orden de cuentas - Cuentas de token incorrectas. Solución: Copiar de los ayudantes de SPL.
- Duplicado no verificado - La misma cuenta dos veces. Solución: Rechazar si es inseguro.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| Constructores de instrucciones SPL | Metadatos correctos | Programas personalizados |
Módulo cpi de Anchor | Generado | Manual |
| Clientes Codama | Solo fuera de la cadena | En la cadena sigue siendo manual |
Preguntas Frecuentes
¿Quién verifica las metadatos?
El programa llamado las revalida.
¿Firmante principal?
Firmantes de la transacción externa + solo invoke_signed.
¿Intento de escritura en solo lectura?
El llamado genera un error.
¿Direcciones ALT?
Se resuelven antes de la ejecución.
¿Muchas cuentas?
Usar el patrón remaining accounts en Anchor.
¿CPI a tu propio programa?
Consideraciones de reentrada.
¿Programa escribible?
Generalmente cuenta de programa de solo lectura.
¿Sysvar en CPI?
Si el llamado lo requiere.
¿Multifirma de token?
Cuentas de firmante adicionales.
¿Registros de simulación?
Muestran el ID del programa del llamado.
¿Costo de clonación de `AccountInfo`?
Bajo.
¿Probar orden incorrecto?
Pruebas negativas de LiteSVM.
Relacionado
- Validación Manual de Cuentas - Validación
- CPI a SPL Token - Diseño del token
- Reentrada y Seguridad - Callbacks de CPI
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.