Aritmética e Overflow
Programas on-chain usam inteiros de tamanho fixo com aritmética com wrap em operações não verificadas. Bugs de overflow e arredondamento drenam cofres, cunham shares sem lastro ou travam contas permanentemente.
Busque em todas as páginas da documentação
Programas on-chain usam inteiros de tamanho fixo com aritmética com wrap em operações não verificadas. Bugs de overflow e arredondamento drenam cofres, cunham shares sem lastro ou travam contas permanentemente.
Cartão de receita de referência rápida - pronto para copiar e colar.
let shares = deposit_amount
.checked_mul(total_shares)
.and_then(|v| v.checked_div(total_assets))
.ok_or(ErrorCode::MathOverflow)?;
// Prefira intermediários u128 para matemática de tokens
let out = (amount_in as u128)
.checked_mul(reserve_out as u128)
.and_then(|n| n.checked_div((reserve_in as u128) + (amount_in as u128)))
.ok_or(ErrorCode::MathOverflow)? as u64;Quando usar isso:
+, -, *, / em quantidades de token.use anchor_lang::prelude::*;
#[account]
pub struct Pool {
pub total_assets: u64,
pub total_shares: u64,
}
pub fn deposit(pool: &mut Pool, amount: u64) -> Result<u64> {
let shares = if pool.total_shares == 0 {
amount
} else {
(amount as u128)
.checked_mul(pool.total_shares as u128)
.and_then(|n| n.checked_div(pool.total_assets as u128))
.ok_or(ErrorCode::MathOverflow)? as u64
};
pool.total_assets = pool
.total_assets
.checked_add(amount)
.ok_or(ErrorCode::MathOverflow)?;
pool.total_shares = pool
.total_shares
.checked_add(shares)
.ok_or(ErrorCode::MathOverflow)?;
Ok(shares)
}
#[error_code]
pub enum ErrorCode {
MathOverflow,
}O que isso demonstra:
u128.checked_add para detectar overflow.[profile.release] overflow-checks = true no Cargo.toml do workspace auditado primeiro - o template do Anchor o define, mas ele é rotineiramente removido para economizar CU. Esta é a ação de auditoria concreta mais barata nesta página.checked_*: um panic de overflow aborta a instrução com um erro genérico em vez do seu erro tipado.checked_* retorna None em overflow - mapeie para erro de programa.amount * bps / 10_000.| Operação | Padrão seguro | Por quê |
|---|---|---|
| Mint shares | Arredondar para baixo | Prevenir over-mint |
| Burn shares | Arredondar dívida para cima | Prevenir sub-colateralização |
| Taxas | Arredondar taxa para cima | Solvência do protocolo |
| Pagamento ao usuário | Arredondar pagamento para baixo | Prevenir dreno de cofre |
use anchor_lang::solana_program::native_token::LAMPORTS_PER_SOL;
const BPS: u128 = 10_000;
let fee = (amount as u128)
.checked_mul(fee_bps as u128)
.and_then(|v| v.checked_add(BPS - 1)) // truque de divisão ceil
.and_then(|v| v.checked_div(BPS))
.ok_or(ErrorCode::MathOverflow)? as u64;+ simples em saldos - Wrap silencioso perto de u64::MAX. Correção: checked_add em todo lugar em saldos de usuário.u128 as u64 trunca silenciosamente. Correção: u64::try_from com verificação de intervalo.i64 sem limites. Correção: Documente intervalos; use checked_* em signed também.| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
Intermediários u128 | Matemática de token padrão | Hot paths críticos em CU (ainda frequentemente vale a pena) |
| Crates fixed-point | Curvas complexas | Matemática de share simples |
| Cálculo off-chain | Somente visualização | Liquidação autoritativa |
Programas implantados usam semântica de release, então depende de [profile.release] overflow-checks. O workspace gerado pelo Anchor 0.32.1 o define como true (operadores simples causam panic); um build de release cargo build-sbf bruto sem ele faz wrap silenciosamente. Verifique a flag em vez de confiar em panics de debug.
Atacante manipula um depósito minúsculo + doação para inflar o preço da share - mitigue com reservas virtuais ou depósito mínimo.
Somente quando o capping é o comportamento pretendido - saldos de cofres devem gerar erro em overflow, não saturar.
Calcule em u128: amount * bps / 10_000 com operações verificadas em cada etapa.
Nunca em liquidação on-chain - floats são não determinísticos entre arquiteturas.
Mapeie cada operação aritmética; use grep para +, *, / sem checked_ no código fonte do programa.
Não - você implementa matemática segura; veja Aritmética Segura.
Escale preços para um expoente comum com pow10 verificado antes de combinar quantidades.
Sim - use fuzzing Trident com quantidades de entrada extremas (Fuzzing de Programas).
Modesto comparado ao custo de exploit - prefira segurança a menos que profiling prove que é um gargalo.
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.
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026