Tratamento de Erros On-Chain
Programas comunicam falha por ProgramResult (Result<(), ProgramError>) ou enums de erro customizados mapeados para códigos. Clientes decodificam esses códigos off-chain para UX e depuração.
Receita
use solana_program::program_error::ProgramError;
fn require_init(data_len: usize, need: usize) -> Result<(), ProgramError> {
if data_len < need {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}Quando usar:
- Substituir panics por falhas de instrução recuperáveis.
- Definir erros de domínio (slippage, expired, unauthorized).
- Propagar erros de helpers com
?.
Exemplo Funcional
use solana_program::program_error::ProgramError;
#[repr(u32)]
pub enum VaultError {
InsufficientFunds = 6000,
Unauthorized = 6001,
}
impl From<VaultError> for ProgramError {
fn from(e: VaultError) -> Self {
ProgramError::Custom(e as u32)
}
}
pub fn withdraw(amount: u64, balance: u64) -> Result<(), ProgramError> {
if amount > balance {
return Err(VaultError::InsufficientFunds.into());
}
Ok(())
}O que isso demonstra:
- Erros customizados usam
ProgramError::Custom(code). - Impl
Fromhabilita?nos handlers de instrução. - Reserve faixas de código por programa para evitar colisões com Anchor.
Aprofundamento
Camadas de Erro
| Camada | Tipo |
|---|---|
| Runtime | ProgramError::InvalidAccountData |
| App | ProgramError::Custom(u32) |
| Anchor | macro atributo error_code |
Mapeamento Off-Chain
- IDL Anchor embute nomes de erro.
- Programas nativos documentam códigos em README ou IDL JSON.
Notas Rust
type VaultResult<T> = Result<T, ProgramError>;Armadilhas
- Panic em expect - Aborta sem código customizado. Correção: Retorne
Errcom variante explícita. - Colisão de código - 6000 pode colidir com outros programas nos mesmos logs de tx. Correção: Namespace códigos; documente por programa.
- Vazar internals - Logs detalhados revelam dicas de exploit. Correção: Log mensagem genérica em público; detalhe em sim privada.
- Ignorar erros de CPI - Deve propagar Result de
invoke. Correção: Use?ou mapeie para seu enum. - Variantes demais - Enums grandes ainda são baratos - mas mantenha mapeamento do cliente atualizado. Correção: Versione IDL junto ao programa.
Alternativas
| Alternativa | Use quando | Não use quando |
|---|---|---|
macro Anchor error! | Export IDL automático | Builds não-Anchor |
| Só builtins ProgramError | Códigos mínimos | UX de produto |
| Events para caminhos de sucesso | Observabilidade rica | Não substitui erros |
FAQs
O que é ProgramResult?
Alias para Result<(), ProgramError>.
Posso retornar dados em erro?
Não - instrução com falha reverte todas as mudanças.
Offset de erro Anchor?
Anchor adiciona offset 6000+ para códigos customizados em 0.32.x.
thiserror on-chain?
Funciona se nenhuma feature só-std estiver habilitada.
Log no caminho de erro?
Permitido mas custa CUs - mantenha curto.
Decode no cliente?
Combine código customizado com enum off-chain.
InvalidAccountData vs Custom?
Builtins são portáteis; custom precisa IDL do programa.
Result em helpers?
Sim - propague com ? no handler de instrução.
macro assert!?
Evite - use retornos explícitos.
Vários erros em uma tx?
Primeira instrução com falha falha a tx inteira (a menos que tratada).
Erros de simulação?
Mesmos códigos da execução on-chain.
Erros em CPI?
Propague ou mapeie deliberadamente - não engula.
Relacionado
- Error Handling Basics - Intro da seção
- Custom Error Enums - Códigos amigáveis ao IDL
- Debugging Failed Transactions - Lendo falhas
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.