Criando um Forta Bot para Detectar Ataques de Governança Financiados por Flash Loans em Tempo Real
Este conteúdo é fornecido **EXCLUSIVAMENTE** para fins de **EDUCAÇÃO** e **TESTES DE SEGURANÇA AUTORIZADOS**.
Available in English
Criando um Forta Bot para Detectar Ataques de Governança Financiados por Flash Loans em Tempo Real
Legal & Ethical Disclaimer
This content is provided for EDUCATIONAL and AUTHORIZED SECURITY TESTING purposes only.
- •Use these techniques on systems you own or have explicit written permission to test
- •Practice in authorized lab environments (VulnHub, HackTheBox, DVWA, etc.)
- •Follow responsible disclosure practices when finding vulnerabilities
- •Use knowledge for defensive security and authorized penetration testing
- •Access systems without explicit authorization
- •Use these techniques for malicious purposes
- •Deploy exploits against production systems you don't own
- •Share working exploits for unpatched vulnerabilities
Legal warning
Unauthorized access to computer systems is illegal in most jurisdictions (e.g. CFAA in the US, Computer Misuse Act in the UK). Violators may face criminal prosecution and civil liability. The author and publisher assume no liability for misuse of this information. By continuing, you agree to use this knowledge ethically and legally.
Hook & Contexto
Em abril de 2022, um atacante tomou emprestado $1 bilhão em um flash loan, usou o capital para adquirir uma participação controladora no token de governança do Beanstalk, aprovou duas propostas maliciosas no mesmo bloco e drenou $182 milhões do protocolo — tudo antes de uma única pessoa conseguir reagir. O ataque não era um bug em uma função Solidity. Era uma exploração lógica do próprio sistema de governança, e foi executado inteiramente dentro da atomicidade de um único bundle de transação Ethereum. Nenhum alarme disparou. Nenhum circuit breaker foi acionado. O protocolo simplesmente não estava ouvindo esse padrão.
Essa é a classe de ataque que auditoria estática baseada em regras não consegue prevenir sozinha. Você não consegue corrigi-la com uma instrução require depois do fato. A superfície de defesa é temporal e comportamental: você precisa detectar a correlação entre uma aquisição massiva de tokens e uma ação de governança e expor isso rápido o suficiente para importar — idealmente antes da execução da proposta, ou no mínimo antes que um segundo ataque na mesma campanha passe despercebido. Monitoramento em tempo real on-chain é a camada da pilha de segurança que fecha essa lacuna.
Forta foi construído especificamente para isso. É uma rede de monitoramento descentralizada onde bots de detecção — programas Node.js/TypeScript que consomem dados blockchain bloco a bloco — são executados continuamente e emitem alertas quando padrões anômalos são encontrados. Este artigo aborda o design racional, estratégia de correlação de dados e calibração de limites para um bot Forta que especificamente procura pelo padrão flash-loan-para-ação-de-governança. Usamos dados históricos de transações do Compound e Beanstalk como âncoras de calibração.
🎯 TL;DR
| Dimensão | Resumo |
|---|---|
| O que você está criando | Um bot de detecção Forta que correlaciona fluxos de tokens de flash loan com votos/propostas de governança dentro de uma janela de blocos configurável |
| Técnica central | Mapeamento de estado por bloco efêmero, endereços mapeados para eventos de aquisição de tokens, limpo e comparado contra logs de eventos de governança |
| Âncoras de calibração | Bloco 14602790 do Beanstalk (ataque), histórico de delegações grandes do Compound |
| Sinal de alerta | O receptor de flash loan aparece em ação de governança dentro de N blocos de receber tokens, onde o delta de token excede o limiar de quórum |
| Desafio-chave | Distinguir delegações legítimas grandes de votação em flash loan maliciosa — resolvido via impressão digital de fonte de empréstimo e proximidade de bloco |
| Ferramentas usadas | Forta SDK, ethers.js, The Graph (calibração histórica), Tenderly (simulação de transação para testes) |
Fundações & Teoria
Por Que Governança É a Nova Superfície de Ataque
Sistemas de governança on-chain transferem o controle do protocolo para detentores de tokens. Essa foi uma decisão de design democratizadora — mas introduziu uma suposição latente: que detentores de tokens estão alinhados economicamente com a saúde de longo prazo do protocolo. Flash loans destroem essa suposição. Um flash loan permite que qualquer endereço mantenha temporariamente um saldo de token arbitrariamente grande pela duração de uma única transação, com zero compromisso econômico além de gas e taxas. Se um sistema de governança aceita um snapshot do saldo de token no momento do voto em vez de em um bloco anterior, esse saldo de flash loan se torna um peso de voto válido.
O padrão de ataque é determinístico:
[Bloco N]
1. Flash loan: emprestar X tokens de governança
2. Votar / criar proposta usando peso emprestado
3. Reembolsar flash loan
↓
[Bloco N ou N+k]
4. Proposta executa (se timelock é zero ou é ignorado)
O insight crítico para detecção é que passos 1–3 são rastreáveis via logs de eventos. Toda transferência ERC-20 emite um evento Transfer(address indexed from, address indexed to, uint256 value). Todo contrato de governança emite VoteCast ou ProposalCreated. A correlação entre essas duas correntes, ancorada na proximidade de tempo de bloco, é o sinal de detecção.
Por Que Detecção em Tempo Real Importa Mesmo Pós-Ataque
Você poderia perguntar: se o ataque é atômico, o que a detecção em tempo real até oferece? Três coisas. Primeiro, ataques em múltiplas etapas — como Beanstalk, que exigiu duas propostas — têm janelas entre propostas onde alertas podem disparar pausas de emergência. Segundo, detecção de campanha: um atacante sondando limites em múltiplos protocolos deixará um rastro entre cadeias que um bot em execução acumula. Terceiro, velocidade forense: geração de alerta mais rápida comprime o tempo até análise pós-mortem, o que importa para reivindicações de seguro, decisões de fork e resposta da comunidade.
Onde Isso Se Encaixa no Fluxo de Trabalho
Em uma pilha de segurança DeFi, bots de detecção ocupam a camada de monitoramento contínuo — distinta de auditoria pré-implantação (análise estática, fuzzing) e resposta a incidentes (multisig do tesouro, pausa de protocolo). Pense na pilha geral como um modelo de defesa em profundidade:
O bot Forta fica nessa terceira camada. Seu trabalho não é prevenir — é detectar e escalar rápido o suficiente para que a camada de resposta a incidente tenha tempo de agir. Para protocolos com governança com timelock (por exemplo, atraso de 48 horas na execução de proposta), um bot alertando dentro de segundos de um voto suspeito dá aos proprietários da multisig uma janela de intervenção significativa.
Conceitos-Chave em Profundidade
1. Subscrição de Fluxo Duplo e o Modelo de Estado Por-Bloco
A fundação deste bot é subscrição simultânea a dois fluxos de eventos e correlação com estado através de uma janela de bloco deslizante. No Forta, sua função handleTransaction é chamada para toda transação em todo bloco. Você também tem acesso a handleBlock para limpeza por bloco.
A arquitetura de estado se parece com isso:
// Estado efêmero: mapeia endereço do destinatário → {amount, blockNumber, txHash}
const flashLoanRecipients: Map<string, FlashLoanEvent[]> = new Map();
// Ações de governança observadas: mapeia endereço → {action, blockNumber, txHash}
const governanceActions: Map<string, GovernanceEvent[]> = new Map();
const BLOCK_WINDOW = 3; // configurável — discutido na seção de calibração
const QUORUM_THRESHOLD = ethers.utils.parseUnits("100000", 18); // específico do protocolo
Em cada transação, você decodifica logs contra duas ABIs: o token de governança (ERC-20 Transfer) e o contrato de governança (VoteCast, ProposalCreated). Quando um evento grande de Transfer é detectado de um endereço de pool de empréstimo conhecido (Aave, dYdX, endereços de pool Uniswap V2/V3), você registra o destinatário. Quando um evento de governança é detectado, você verifica se o remetente aparece em flashLoanRecipients dentro de BLOCK_WINDOW blocos.
A decisão de design-chave é de onde você obtém a "impressão digital de flash loan". Você tem duas estratégias:
- Impressão digital de endereço de origem: mantenha uma lista de endereços de pool de empréstimo conhecido e provedores de flash loan. Uma
Transferde um desses para um novo endereço é provavelmente um desembolso de flash loan. - Padrão de transferência de retorno: flash loans exigem reembolso, então você verá uma
Transfersimétrica de saída do destinatário de volta para o pool dentro do mesmo bloco. Este é o sinal mais forte, mas requer consciência de ordenação intra-bloco.
Para um bot de produção, use ambas. A impressão digital de origem dispara cedo (no recebimento); o padrão de retorno dispara como confirmação.
2. Decodificação de ABI e Filtragem de Log no Forta SDK
Bots Forta recebem um objeto TransactionEvent que expõe filterLog(abi, address) — um método de conveniência envolvendo a decodificação da interface ethers.js. O aspecto elegante desse design é que você pode filtrar múltiplas assinaturas de evento em uma única passagem:
import { Finding, FindingSeverity, FindingType, HandleTransaction, TransactionEvent } from "forta-agent";
import { GOVERNANCE_ABI, TOKEN_ABI, KNOWN_LENDING_POOLS } from "./constants";
const handleTransaction: HandleTransaction = async (txEvent: TransactionEvent) => {
const findings: Finding[] = [];
// Decodifique transferências de token grandes DE fontes de flash loan conhecidas
const transferLogs = txEvent.filterLog(TOKEN_ABI, GOVERNANCE_TOKEN_ADDRESS);
for (const log of transferLogs) {
const { from, to, value } = log.args;
if (KNOWN_LENDING_POOLS.has(from.toLowerCase()) && value.gte(QUORUM_THRESHOLD)) {
recordFlashLoanRecipient(to, value, txEvent.blockNumber, txEvent.hash);
}
}
// Decodifique ações de governança
const voteLogs = txEvent.filterLog(GOVERNANCE_ABI, GOVERNOR_ADDRESS);
for (const log of voteLogs) {
const voter = log.args.voter ?? log.args.proposer;
const finding = checkCorrelation(voter, txEvent.blockNumber, txEvent.hash);
if (finding) findings.push(finding);
}
return findings;
};
Uma nota de implementação crítica: filterLog retorna eventos decodificados para a transação inteira, não apenas logs do contrato principal. Isso importa porque orquestração de flash loan tipicamente acontece através de um contrato de atacante personalizado que chama governança na mesma transação — os eventos aparecem no mesmo array de log de transação independentemente da profundidade de chamada.
3. Gerenciamento de Estado de Janela Deslizante e Limpeza de Bloco
Estado efêmero que nunca expira cria vazamentos de memória e falsos positivos de dados obsoletos. O hook handleBlock é seu mecanismo de limpeza:
const handleBlock = async (blockEvent: BlockEvent) => {
const currentBlock = blockEvent.blockNumber;
// Remova entradas mais antigas que BLOCK_WINDOW
for (const [address, events] of flashLoanRecipients.entries()) {
const filtered = events.filter(e => currentBlock - e.blockNumber <= BLOCK_WINDOW);
if (filtered.length === 0) {
flashLoanRecipients.delete(address);
} else {
flashLoanRecipients.set(address, filtered);
}
}
return [];
};
Por que BLOCK_WINDOW importa arquiteturalmente: ataques no mesmo bloco (como Beanstalk) exigem BLOCK_WINDOW = 0 para detectar com certeza, mas definir a janela para 1–3 blocos também pega ataques de múltiplas transações onde o atacante empresta no bloco N e vota no bloco N+1 antes de reembolsar no bloco N+2 (um padrão que pode evitar detecção no mesmo bloco se o contrato de governança apenas verifica o saldo atual).
4. Calibração de Limiar Usando Dados Históricos
É aqui que o bot se move de brinquedo para qualidade de produção. Limiares descalibrados são a razão principal pela qual bots de monitoramento falham na prática — ou afogando operadores em ruído ou perdendo ataques reais.
Calibrando contra Beanstalk (bloco 14602790): O atacante adquiriu aproximadamente 79 milhões de Stalk (peso de governança). No momento do ataque, a oferta total de Stalk era aproximadamente 170 milhões, tornando o peso do ataque ~46% da oferta total. Seu QUORUM_THRESHOLD para Beanstalk deveria ter sido definido bem abaixo de 46% da oferta — algo como 10–15% da oferta em circulação como disparo, já que nenhum votante legítimo único manteria essa proporção através de um flash loan.
Calibrando contra delegações legítimas grandes do Compound: O histórico de governança do Compound inclui endereços como 0xa2869... (delegação a16z) segurando 8–10% do COMP através de meios legítimos. As características distintivas são:
- A delegação não foi adquirida no mesmo ou bloco adjacente como um voto
- A fonte do token era uma multisig ou carteira VC conhecida, não um pool de empréstimo
- A participação persistiu através de milhares de blocos
A partir disso, derive dois eixos de calibração:
| Eixo | Sinal Malicioso | Sinal Legítimo |
|---|---|---|
| Fonte do token | Pool de empréstimo conhecido | Multisig / exchange / carteira com posse de longo prazo |
| Proximidade de bloco | Mesmo ou ≤3 blocos entre aquisição e voto | Semanas/meses de posse anterior |
| Delta de token | >10% da oferta em circulação | <5% em um evento de aquisição único |
| Histórico de endereço | Votante de primeira vez, sem participação anterior em governança | Endereço com histórico de governança |
Usando The Graph, consulte eventos VoteCast históricos e faça referência cruzada de idades de endereço de votante contra timestamps de aquisição de token. Qualquer endereço que recebeu tokens de governança pela primeira vez no mesmo bloco em que votou é um ponto de calibração perfeito para BLOCK_WINDOW = 0.
5. Estrutura de Alerta e Design de Escalação
Um Finding em Forta não é apenas uma entrada de log — é um alerta estruturado com severidade, tipo, metadados e rótulos de protocolo que consumidores downstream (webhooks Tenderly, PagerDuty, bots Discord) podem agir. Projete seu alerta para carregar contexto forense máximo:
Finding.fromObject({
name: "Flash Loan Governance Attack Detected",
description: `Address ${voter} cast governance vote within ${blockDelta} blocks of receiving ${formattedAmount} tokens from flash loan source ${loanSource}`,
alertId: "FLASH-LOAN-GOV-1",
severity: blockDelta === 0 ? FindingSeverity.Critical : FindingSeverity.High,
type: FindingType.Exploit,
metadata: {
voter,
loanSource,
tokenAmount: amount.toString(),
acquisitionBlock: acquisitionBlock.toString(),
voteBlock: voteBlock.toString(),
proposalId: proposalId ?? "unknown",
blockDelta: blockDelta.toString(),
},
protocol: "compound-v2", // ou dinâmico
addresses: [voter, loanSource],
});
Gradação de severidade importa para resposta de operador. Um alerta Critical (mesmo bloco) deve disparar uma ação de emergência automatizada se seu protocolo tiver uma. Um alerta High (janela de 1–3 blocos) deve paginar um responsável on-call. Medium (>3 blocos, aquisição grande, votante de primeira vez) deve registrar em um dashboard para revisão humana.
Alternativas & Comparação
| Abordagem | Forças | Fraquezas |
|---|---|---|
| Bot Forta (esta abordagem) | Tempo real, descentralizado, componível, alertas estruturados | Requer manutenção, bots podem perder eventos se mal subscritos |
| Webhooks Tenderly | Fácil setup, UI excelente | Centralizado, lógica de correlação limitada, fadiga de alerta |
| The Graph + polling por cron | Consultas históricas ricas, ótimo para janelas de múltiplos blocos | Latência (minutos, não segundos), não verdadeiramente tempo real |
| Custom RPC mempool watcher | Latência mais baixa (pré-confirmação) | Pesado em infraestrutura, requer nó archive, sem descentralização |
| Chainalysis / TRM Labs | Qualidade compliance, entre cadeias | Caro, não aberto, não customizável para lógica específica do protocolo |
Para protocolos DeFi com governança ao vivo, Forta + roteamento de alerta Tenderly é a pilha prática: Forta manipula a lógica de detecção; Tenderly manipula a entrega e simulação legível por humano da transação detectada para que respondentes verifiquem em menos de 60 segundos.
Aprendizados & Leitura Complementar
O ataque Beanstalk não é uma anomalia histórica — é um blueprint que outros atacantes seguirão conforme o poder de governança continua se concentrando em tokens líquidos e emprestáveis. O bot de detecção descrito aqui não é uma bala de prata: não pode impedir um ataque atômico de ser completado, mas pode detectar o padrão, alertar a tempo para campanhas de múltiplas etapas, e construir um registro forense que colapsa investigação pós-incidente de semanas para horas.
Os três princípios de design que tornam este bot qualidade de produção em vez de prova de conceito:
- Correlação de fluxo duplo sobre alerting de evento único — um evento em isolamento nunca é sinal suficiente
- Limiares calibrados historicamente — construa seu ajuste a partir de dados reais on-chain, não intuição
- Alertas estruturados e acionáveis — um alerta que não diz ao respondente exatamente o que procurar é ruído
📚 Leitura Complementar:
- Documentação do Forta SDK — comece com o SDK TypeScript
forta-agente o ciclo de vida dehandleTransaction - Análise Pós-Mortem do Beanstalk — fonte primária para mecânica de ataque e forense em nível de bloco
- Análise de Governança do Compound via The Graph — use este subgraph para consultas de dataset de calibração
- Monitoramento de Flash Loan do Euler Finance — uma implementação de referência de monitoramento DeFi de produção
- "Flash Boys 2.0" (Daian et al., 2020) — a fundação acadêmica para entender MEV e composabilidade de transação atômica, contexto essencial para por que flash loans são poderosos
- OpenZeppelin Defender Sentinels — uma alternativa centralizada complementar que vale a pena entender antes de decidir sobre Forta
A superfície de ataque de governança crescerá apenas conforme protocolos DeFi amadurecem e o poder de governança acumula valor econômico real. Construa a camada de monitoramento agora, calibre-a contra histórico, e trate-a como um artefato de engenharia de primeira classe — não um afterthought parafusado depois que o exploit já executou.