Decodificador de logs de eventos Ethereum

Transforme entradas de log brutas (address, topics, data) em eventos e parâmetros nomeados. Mais de quarenta eventos comuns são reconhecidos automaticamente; cole a ABI do contrato para qualquer outro. Todos os logs de um recibo são decodificados de uma vez.

Abas "Logs" de exploradores, viem, ethers e envelopes JSON-RPC funcionam; todos os logs de um recibo são decodificados.
Exemplos:

Calculado no seu navegador com JavaScript. Os endereços nunca são enviados nem armazenados.

O que é um log de evento?

Um log de evento é o registro que um contrato EVM grava ao executar os opcodes LOG0–LOG4 (emit no Solidity). Cada entrada contém o endereço do contrato emissor, até quatro topics de 32 bytes e um campo data de comprimento arbitrário. Decodificar um log significa casar topics[0] com a assinatura de um evento, ler os parâmetros indexed dos topics restantes e decodificar via ABI os parâmetros não indexados a partir de data. Os exploradores fazem isso com o código-fonte verificado; esta página faz isso só a partir da assinatura, para mais de quarenta eventos comuns, ou a partir de qualquer ABI que você colar.

Como um log é codificado

CampoConteúdoExemplo (Transfer ERC-20)
addressO contrato que emitiu o evento0xdAC17F958D2ee523a2206206994597C13D831ec7 (USDT)
topics[0]keccak256 da assinatura canônica0xddf252ad… = keccak256("Transfer(address,address,uint256)")
topics[1]Primeiro parâmetro indexado, preenchido à esquerda até 32 bytesendereço from
topics[2]Segundo parâmetro indexadoendereço to
dataCodificação ABI de todos os parâmetros não indexadosvalue de 32 bytes

Parâmetros indexados de tipo estático (address, inteiros, bool, bytes1–32) são armazenados diretamente no topic. Parâmetros indexados de tipo dinâmico (string, bytes, arrays, structs) são substituídos pelo hash Keccak-256 da sua codificação, como descreve a seção de eventos da especificação ABI do Solidity; o decodificador os marca como hasheados.

Exemplo prático: uma transferência de USDT

Clique em "Transfer ERC-20" acima. topics[0] casa com a assinatura Transfer e, como há exatamente três topics, o layout ERC-20 (dois endereços indexados) é escolhido em vez do layout ERC-721 (três indexados). topics[1] decodifica para from = 0xd8dA6BF2…96045, topics[2] para to = 0x1111…1111, e a única palavra de data 0x17d7840 é value = 25000000, que com as seis casas decimais do USDT equivale a 25 USDT. O mesmo mecanismo decodifica um Swap do Uniswap V2 (dois endereços indexados, quatro valores em data) ou um TransferBatch ERC-1155, cujo campo data contém dois arrays dinâmicos com offsets e comprimentos.

Eventos reconhecidos sem ABI

A tabela abaixo é gerada na página a partir da mesma lista de assinaturas que o decodificador usa, então cada valor de topics[0] é um autoteste da implementação de Keccak. Ela cobre Transfer e Approval de ERC-20 e ERC-721, ApprovalForAll, TransferSingle, TransferBatch e URI de ERC-1155, Deposit e Withdrawal de WETH, Swap, Sync, Mint, Burn e PairCreated do Uniswap V2, Swap, Mint, Burn, Collect e PoolCreated do Uniswap V3, OwnershipTransferred, Upgraded, AdminChanged e BeaconUpgraded de EIP-1967, os eventos de Initializable, Pausable e AccessControl, Approval, Permit, NonceInvalidation e Lockdown do Permit2, Deposit e Withdraw de ERC-4626, e ExecutionSuccess, ExecutionFailure, SafeMultiSigTransaction, mudanças de owner e threshold, SafeSetup e ProxyCreation do Safe.

Entradas aceitas

Relacionado: calcule o hash de topic de qualquer assinatura com a calculadora de seletores e topics, decodifique o calldata da transação com o decodificador ABI ou inspecione uma transação bruta com o decodificador de transações Ethereum.

Perguntas frequentes

O que são topics e data em um log da Ethereum?

Um log tem até quatro topics de 32 bytes e um campo data de comprimento variável. topics[0] é o hash Keccak-256 da assinatura do evento (a menos que o evento seja anonymous); topics[1..3] guardam os parâmetros indexed, um por topic; todo parâmetro não indexado é codificado via ABI em data, na ordem de declaração, exatamente como argumentos de função.

Por que um string ou bytes indexado mostra um hash?

A EVM não consegue colocar um valor dinâmico em um topic de 32 bytes, então o Solidity armazena o keccak256 do valor no lugar. O string original não pode ser recuperado do log; ele só pode ser comparado com um candidato aplicando hash a esse candidato. Endereços, inteiros, bool e bytesN são armazenados por inteiro e decodificam normalmente.

Transfer de ERC-20 e ERC-721 têm o mesmo topics[0]. Como são diferenciados?

Ambos têm a assinatura Transfer(address,address,uint256), então topics[0] é idêntico. O ERC-721 indexa tokenId, resultando em quatro topics e data vazio; o ERC-20 indexa apenas from e to, resultando em três topics e um campo data de 32 bytes. O decodificador escolhe o layout cuja contagem de indexados corresponde ao log.

E se o evento não for reconhecido?

O log é exibido em bruto com topics[0] destacado. Cole a ABI do contrato (apenas os eventos já bastam) ou uma única linha como event Bid(address indexed bidder, uint256 amount) na caixa de ABI e decodifique de novo. Bancos de assinaturas como 4byte.directory e openchain.xyz podem ajudar a identificar um hash de topic desconhecido.

Como funcionam os eventos anonymous?

Um evento declarado anonymous não tem topic de assinatura, então todos os seus topics são parâmetros indexados e nada o identifica on-chain. O decodificador só consegue casá-lo com eventos anonymous da ABI que você fornecer, pela contagem de topics, e informa isso em uma nota.

Os valores são convertidos para unidades do token?

Os inteiros são exibidos como decimais exatos. Para valores uint256, uma dica mostra o valor dividido por 1018 e 106, o que cobre ETH, a maioria dos ERC-20, USDC e USDT. Para outras casas decimais use o conversor de decimais de token; o decodificador não conhece as casas decimais de cada token.

Algo é enviado para servidores?

Não. Os hashes de topic da tabela integrada são calculados com Keccak-256 no seu navegador ao carregar a página, e a decodificação roda localmente. A página não faz requisições de rede depois de carregada.