Dados de entrada de transações no Ethereum: bytes e decodificação ABI

Os dados de entrada de uma transação no Ethereum ficam em um campo opcional que pode conter dados arbitrários. Em uma chamada de função que segue o padrão ABI, esses bytes têm uma estrutura reconhecível: um seletor de função seguido dos argumentos codificados. Interpretar essa estrutura exige o esquema da interface correspondente.

Uma leitura útil separa três perguntas: quais bytes estão presentes, como determinado esquema os interpreta e quais conclusões continuam sem comprovação. Uma entrada vazia, um seletor reconhecível e um número decodificado respondem, cada um, apenas a parte dessas perguntas.

O que o campo de entrada contém

A documentação de transações do Ethereum descreve os dados de entrada como opcionais e capazes de conter dados arbitrários. Essa definição ampla importa: nem toda entrada precisa seguir a convenção de chamadas de função da ABI. Comece pelos bytes efetivamente apresentados antes de atribuir um nome de função ou um tipo de argumento.

Para sequências de bytes, o JSON-RPC do Ethereum usa texto hexadecimal com o prefixo 0x, no qual dois dígitos hexadecimais representam cada byte. As convenções de codificação do JSON-RPC distinguem essa representação, chamada DATA, da formatação usada para quantidades numéricas. Preserve essa distinção ao ler um campo de entrada.

Na representação de sequências de bytes, 0x significa uma sequência vazia: não há bytes de dados depois do prefixo. Essa representação difere da codificação da quantidade numérica zero. Descreva o conteúdo como entrada vazia, sem tratá-lo como um número à espera de decodificação.

Como o seletor e os argumentos se organizam

A especificação da ABI de contratos do Solidity coloca o seletor de função nos primeiros quatro bytes dos dados de uma chamada de função padrão, também chamados de calldata. Os argumentos codificados começam no quinto byte, quando há argumentos. Essa organização não implica que toda função exija argumentos, nem descreve qualquer sequência arbitrária de entrada.

O seletor corresponde aos primeiros quatro bytes do hash Keccak-256 da assinatura canônica da função. Essa assinatura usa o nome da função seguido dos tipos dos parâmetros entre parênteses, separados por vírgulas e sem espaços. Os tipos precisam seguir suas representações canônicas na ABI; os valores específicos dos argumentos não fazem parte dessa assinatura.

Considere uma função inventada para uma aula, com um parâmetro uint256, cuja assinatura canônica seja record(uint256). A assinatura identifica o nome da função e o tipo do parâmetro nesse exercício. Um valor específico, como 6, pertence à região dos argumentos codificados. Aqui, não calculamos nem atribuímos um valor de seletor a essa função fictícia.

Ao fazer anotações sobre uma chamada ABI padrão, identifique separadamente o seletor e a região dos argumentos. Assim, a descrição da interface fica ao lado dos bytes que ela ajuda a interpretar. Para entender o programa ao qual a chamada se dirige, consulte nosso guia sobre código, estado e funções de contratos inteligentes.

Por que o esquema da ABI é necessário

A codificação ABI não descreve a própria estrutura. Sua decodificação exige um esquema que forneça os tipos e a organização relevantes. Uma ABI adequada ao contrato oferece essas informações, embora um arquivo JSON específico não seja a única forma de representar o conhecimento necessário sobre os tipos.

É fácil deixar esse requisito passar quando uma ferramenta exibe um nome de função familiar. A documentação de transações do Ethereum ilustra a ambiguidade de seletores com 0xa9059cbb: a explicação identifica várias funções candidatas conhecidas para esse seletor. O exemplo sustenta a possibilidade de haver múltiplas candidatas. Ele não comprova que todo seletor tenha várias correspondências conhecidas.

Por isso, uma consulta de seletor deve permanecer como uma etapa de identificação de candidatas enquanto a interface do contrato de destino não estiver estabelecida. Em um exercício de leitura, anote de onde vem o esquema. Se ele for apenas uma premissa do exercício, deixe isso explícito. Se continuar desconhecido, mantenha a interpretação dos tipos em aberto, sem apresentar um rótulo plausível como informação comprovada.

Um argumento hipotético que corresponde ao número 6

Considere um exercício hipotético com três premissas explícitas: a entrada é uma chamada ABI padrão corretamente formada, seu seletor corresponde à função pretendida e essa função possui exatamente um argumento uint256. Depois dos quatro bytes do seletor, o exercício apresenta esta palavra de argumento:

0000000000000000000000000000000000000000000000000000000000000006

A palavra contém 31 bytes iguais a zero, seguidos de 06. A codificação ABI padrão representa os inteiros sem sinal compatíveis como valores de 32 bytes em ordem big-endian, com preenchimento de bytes zero à esquerda. Essa regra se aplica a esses tipos inteiros na codificação ABI padrão; ela não é uma regra geral de decodificação para todos os tipos de dados ou para qualquer entrada de transação.

A dedução depende das premissas: o esquema definido no exercício identifica a palavra após o seletor como um uint256, e a regra de codificação de inteiros sem sinal leva ao inteiro 6. A posição do argumento, o esquema e a regra de codificação, em conjunto, sustentam essa interpretação.

Agora retire o esquema do exercício. Como a codificação não descreve a própria estrutura, a palavra terminada em 06, isoladamente, não permite estabelecer que seu tipo seja uint256. Evidências adicionais sobre a interface poderiam estabelecer esse tipo, mas os bytes sozinhos não fornecem a premissa ausente. O exemplo também não comprova que alguma transação real tenha ocorrido ou sido executada.

O que uma entrada vazia permite concluir

Uma entrada vazia contém zero bytes, enquanto um seletor ABI padrão exige quatro bytes. Dessas duas premissas, podemos deduzir que uma entrada vazia não contém um seletor de função ABI padrão. Essa conclusão diz respeito aos bytes disponíveis. Ela não determina o tipo da conta de destino.

Separadamente, a documentação de transações do Ethereum descreve uma transação direcionada a uma conta de contrato como uma transação que executa o código do contrato. Essa afirmação geral não identifica um caminho específico de tratamento nem comprova que a execução tenha sido bem-sucedida.

Em um segundo exercício hipotético, estabeleça como premissas uma conta de contrato como destino e uma entrada vazia. A ausência de bytes de seletor e a regra referente ao destino de contrato podem se aplicar ao mesmo tempo. A dedução resultante é limitada: não ter seletor não implica ausência de execução de código do contrato. Determinar o caminho específico de tratamento ou o resultado exigiria evidências adicionais.

Checklist para ler dados de entrada

  1. Identifique a representação. Leia o campo como uma sequência de bytes DATA, mantendo separada a formatação de quantidades numéricas.
  2. Confira se a entrada está vazia. Registre 0x como zero bytes de entrada, sem atribuir um tipo de destino ou um resultado de execução.
  3. Estabeleça a convenção de codificação. Aplique a organização em seletor e argumentos quando a codificação ABI padrão de chamadas de função for a premissa pertinente.
  4. Registre o esquema. Identifique as evidências sobre a interface ou declare claramente os tipos de parâmetros definidos para o exemplo hipotético.
  5. Mantenha os nomes candidatos como possibilidades. Uma consulta de seletor pode ser ambígua e, isoladamente, não estabelece a interface do destino.
  6. Explique cada dedução. Relacione o valor decodificado à posição do argumento, ao esquema de tipos e à regra de codificação.

Use essas perguntas para manter a leitura dos bytes precisa. O checklist organiza a interpretação; ele não certifica a segurança de um contrato. A atribuição às fontes identifica a base da explicação, sem comprovar a segurança de uma interação específica.

Material educativo preparado com auxílio de IA. Os exemplos hipotéticos explicam a decodificação de dados de entrada e não constituem recomendação de ação financeira.