Um relato técnico da auditoria que encontrou 3 vulnerabilidades críticas em um protocolo DeFi com R$ 2M em TVL — o vetor de ataque, a exploração e como foi corrigido.
Disley Souza
1 de maio de 2026
Em março de 2026, auditamos um protocolo de staking com R$ 2 milhões em TVL. Encontramos 3 vulnerabilidades críticas antes do lançamento público. Este é o relato técnico completo — os vetores de ataque, as explorações e as correções.
NDA em vigor para dados do cliente. Endereços de contratos, nomes e quantias exatas foram alterados. O código de exploração é real.
O cliente construiu um protocolo de staking com recompensas variáveis em Token-2022. O escopo incluía o programa principal em Anchor, dois programas auxiliares e a lógica de distribuição de recompensas. Três semanas de trabalho, dois auditores.
A instrução `unstake` não validava que o chamador era o dono da conta de staking. Qualquer carteira poderia remover tokens de qualquer usuário.
// VULNERÁVEL — sem validação de ownership
#[derive(Accounts)]
pub struct Unstake<'info> {
#[account(mut)]
pub stake_account: Account<'info, StakeAccount>,
pub user: Signer<'info>,
// Faltava: constraint = stake_account.owner == user.key()
}A correção exige um constraint explícito no macro `#[account]` ou validação manual dentro da instrução:
// CORRIGIDO
#[derive(Accounts)]
pub struct Unstake<'info> {
#[account(
mut,
constraint = stake_account.owner == user.key() @ StakeError::Unauthorized
)]
pub stake_account: Account<'info, StakeAccount>,
pub user: Signer<'info>,
}A instrução `claim_rewards` chamava um programa externo via CPI antes de zerar o saldo de recompensas. Um atacante poderia criar um programa malicioso que re-entrasse no protocolo durante a CPI, dobrando o saque.
Solana não tem reentrância no sentido EVM — mas CPIs para programas não confiáveis podem simular o mesmo padrão. Sempre zere o estado antes de chamar programas externos.
// PADRÃO CORRETO: checks-effects-interactions
pub fn claim_rewards(ctx: Context<ClaimRewards>) -> Result<()> {
let rewards = ctx.accounts.stake_account.pending_rewards;
// 1. Zera ANTES da CPI (effect)
ctx.accounts.stake_account.pending_rewards = 0;
// 2. Transfere depois (interaction)
transfer_tokens(&ctx, rewards)?;
Ok(())
}O cálculo de recompensas usava multiplicação em `u64` sem checar overflow. Com valores grandes de stake e tempo, o resultado silenciosamente wrapeava para um número pequeno — o usuário recebia quase zero em vez de uma quantia alta.
// VULNERÁVEL — overflow silencioso em release builds
let rewards = stake_amount * reward_rate * time_elapsed; // pode overflow
// CORRIGIDO — usar checked arithmetic
let rewards = stake_amount
.checked_mul(reward_rate)
.and_then(|r| r.checked_mul(time_elapsed))
.ok_or(StakeError::MathOverflow)?;Essas três vulnerabilidades teriam custado R$ 2M ao protocolo. Foram encontradas antes do deploy. O tempo de auditoria foi 3 semanas; o custo de não auditar teria sido catastrófico. Se você está construindo um protocolo com TVL real, contate-nos antes do lançamento — não depois.
Próximo passo
Auditoria de segurança, arquitetura de sistemas blockchain, integração Solana — trabalhamos com equipes que não aceitam o suficiente.