Somente para fins educacionais; não constitui recomendação nem aconselhamento de investimento. Investir pode causar perdas.
Resposta direta
Calldata é a sequência imutável de bytes fornecida como entrada para uma transação de nível superior do Ethereum ou uma chamada interna. Uma chamada convencional de função Solidity começa com um seletor de 4-byte, seguido por argumentos codificados em ABI, mas calldata não se descreve: os mesmos bytes podem ter significados diferentes para códigos em execução, implementações de proxy ou esquemas distintos. Funções fallback, assembly bruto e protocolos que não usam Solidity não precisam seguir a ABI convencional de funções.
Por isso, uma carteira deve mostrar mais do que um possível nome de função. Uma revisão segura vincula os bytes a chainId, um bloco, from, to, value nativo, codeHash em execução, implementação ativa e ABI confiável; decodifica estritamente cada chamada aninhada; distingue calldata on-chain de assinaturas EIP-712; simula em um estado explícito; e reconcilia o recibo e as mudanças de estado reais após a inclusão.
A conclusão desta revisão não prova que um ativo, transação ou sistema seja seguro.
Como funciona
- Fixe o envelope de assinatura e o ponto de observação:
chainId, número e hash do bloco,from,to,valuenativo, bytes de entrada, nonce e campos de taxas. Preserve a fonte da carteira ou RPC; um payload decodificado em outra rede ou bloco não é a mesma afirmação. - Classifique o objeto antes da decodificação. Transação, solicitação de dados tipados EIP-712, permit ERC-2612, UserOperation ERC-4337 e mensagem personal-sign bruta usam domínios e esquemas diferentes; não force todos a passar pela ABI de transações.
- Resolva o destino no bloco fixado. Leia o bytecode em execução e o
codeHash; identifique proxy, beacon ou implementação quando aplicável; registre slots de implementação e administração; e obtenha uma ABI correspondente àquela versão exata do código. Um registro de seletores fornece candidatos, não autoridade. - Decodifique estritamente. O seletor corresponde aos primeiros
4 bytesdo Keccak-256 da assinatura canônica da função, excluindo tipos de retorno. Valores estáticos ocupam palavras de32-byte; cabeçalhos dinâmicos contêm offsets medidos desde o bloco de argumentos posterior ao seletor. Rejeite dados truncados, offsets fora dos limites, comprimentos impossíveis, padding inválido e bytes finais sem explicação. - Expanda recursivamente multicalls, calldata aninhada e execução delegada. Para cada chamada filha, liste destino, valor nativo, seletor, argumentos, tipo de chamada e eventual indicador
allowFailure. Comdelegatecall, o código da implementação roda no contexto de endereço, saldo e armazenamento do chamador, preservandomsg.senderemsg.value. - Construa registros separados de autoridade e valor e depois simule. Registre destinatários, spenders, operadores de NFT, unidades brutas de tokens, decimais, prazos, limites de slippage e valor nativo. Simule com bloco, remetente e valor exatos, mas trate o resultado como fotografia condicional, pois estado, preços, tempo, código e ordenação das transações podem mudar.
- Confirme cada campo relevante antes de assinar. Depois da inclusão, inspecione status do recibo, logs, traces disponíveis e variações de saldo, allowance e estado dos operadores; diferencie falhas filhas capturadas de sucesso no nível superior; contabilize gás mesmo em revert; aguarde a finalidade exigida; e pare em vez de assinar novamente uma falha sem explicação.
Exemplos resolvidos
- Transferência ERC-20 estática.
transfer(address,uint256)normalmente usa o seletor0xa9059cbb. Um seletor e duas palavras ABI totalizam4 + 2 * 32 = 68 bytes. Um valor bruto de1,500,000de um token cuja utilização de6 decimalsfoi verificada independentemente aparece como1.5 tokens. Os decimais são metadados externos do contrato, não estão codificados nesses argumentos, e o seletor sozinho não identifica exclusivamente o contrato ou a função. - Offset de bytes dinâmicos. Para
f(address,bytes)com payload de3-byte, o cabeçalho de duas palavras ocupa64 bytes. O offset dinâmico é0x40, medido desde o início do bloco de argumentos e sem contar o seletor. Sua cauda contém uma palavra de comprimento de32-bytee uma palavra de dados com padding de32-byte, portanto a calldata total é4 + 64 + 32 + 32 = 132 bytes. Tratar o offset como absoluto desde o byte zero desloca o destino em quatro bytes. - O valor de um lote depende da implementação. Uma chamada externa leva
1.00 ETH; três chamadas filhas decodificadas solicitam explicitamente0.20 ETH,0.30 ETHe0.10 ETH, totalizando0.60 ETH. Os0.40 ETHrestantes podem ser devolvidos, retidos, encaminhados ou causar revert, conforme o código do lote. Se a terceira chamada falhar comallowFailure=true, as anteriores podem permanecer confirmadas; uma implementação atômica pode reverter tudo. - Um permit não é a calldata do relayer no momento da assinatura. Um proprietário com
1,000 USDCassina um permit ERC-2612 de300 USDCno nonce41. A assinatura isolada não altera saldo nem allowance. Depois que um relayer a envia com sucesso, o nonce passa a42e a allowance a300; depois que o spender usa180, o saldo é820e a allowance restante120. Desconectar o site não revoga a permissão.
Riscos
- Decodificar com rede, fork, block tag ou envelope de transação incorretos.
- Assinar para domínio, endereço de destino ou destinatário falsificados.
- Tratar um seletor de
4-bytecomo único, apesar de possíveis colisões. - Usar ABI presumida, obsoleta ou verificada incorretamente.
- Confiar em um rótulo de fonte verificada sem comparar o
codeHashatual. - Não perceber uma atualização de implementação, beacon ou administrador entre revisão e execução.
- Ignorar uma função do proxy cujo seletor colide com a implementação.
- Esquecer que
delegatecallgrava no contexto de armazenamento do chamador. - Aceitar offsets, comprimentos, padding ou bytes finais dinâmicos malformados.
- Não expandir um lote aninhado que oculta destinos, valores ou permissões.
- Presumir atomicidade quando a implementação captura ou permite falhas filhas.
- Ignorar o
valuenativo de nível superior porque os argumentos de token parecem inofensivos. - Aplicar decimais errados ou presumir que tokens com taxa de transferência e rebasing são ERC-20 padrão.
- Conceder allowance ERC-20 ilimitada ou tratar incorretamente a corrida na atualização da allowance.
- Ignorar o alcance sobre toda a coleção de
setApprovalForAllpara NFT. - Confundir dados tipados EIP-712 ou permit ERC-2612 com calldata de transação.
- Não verificar nonce, prazo, contrato verificador, domínio da rede ou limites de replay.
- Tratar a simulação como estável apesar de mudanças de oráculo, timestamp, estado pendente, MEV ou código.
- Tratar status do recibo, logs ou traces do provedor como prova completa do estado econômico.
- Assinar novamente às cegas em uma UI comprometida ou ignorar riscos de inclusão, reorganização e finalidade.
Equívocos comuns
- Um seletor de função identifica de forma única o que o contrato executará.
- Um resumo verificado do frontend é idêntico aos bytes e à implementação atual assinados.
- Uma transação com
value=0não pode mover tokens, NFTs ou ativos delegados. - Simulação bem-sucedida ou recibo de sucesso provam segurança e o resultado econômico pretendido.
- Desconectar uma dapp revoga aprovações, permits e permissões de operadores de NFT.
Tópicos relacionados
Fontes
- Contract ABI Specification - Solidity Documentation (acessado em: 2026-08-12)
- Introduction to Smart Contracts - Solidity Documentation (acessado em: 2026-08-12)
- Transactions - Ethereum.org (acessado em: 2026-08-12)
- ERC-20: Token Standard - Ethereum Improvement Proposals (acessado em: 2026-08-12)
- EIP-712: Typed structured data hashing and signing - Ethereum Improvement Proposals (acessado em: 2026-08-12)
- ERC-2612: Permit Extension for EIP-20 Signed Approvals - Ethereum Improvement Proposals (acessado em: 2026-08-12)
- ERC-721: Non-Fungible Token Standard - Ethereum Improvement Proposals (acessado em: 2026-08-12)
- ERC-1967: Proxy Storage Slots - Ethereum Improvement Proposals (acessado em: 2026-08-12)