Modelos UTXO e de contas · Aula 3 de 6
O modelo de contas para analistas
9 min de leitura
Ethereum e as muitas redes que copiam seu design mantêm um saldo atualizado para cada endereço, em vez de um conjunto de moedas discretas. Isso muda o que pode ser rastreado, o significado de uma "transação" e quem é o verdadeiro agente por trás de uma ação. Com as contas inteligentes e a abstração de contas agora comuns, o endereço que assina, o endereço que paga o gás e o endereço que aparece no campo from costumam ser três coisas diferentes; um analista que as confunde atribuirá a atividade à parte errada.
Estado, não moedas
Uma blockchain baseada em contas armazena um estado global: um mapeamento de cada endereço de 20 bytes para um registro de conta. No Ethereum, esse registro tem quatro campos:
| Campo | Significado | Uso para o analista |
|---|---|---|
nonce | Transações enviadas (EOA) ou contratos criados (contrato) | Contagem de atividade, ordenação, verificações de endereços novos |
balance | Moeda nativa, em wei | Ativos em um bloco |
codeHash | Hash do código da conta (vazio para uma EOA simples) | Diferenciar EOAs, contratos e EOAs delegadas |
storageRoot | Raiz do armazenamento de chave-valor da conta | Onde os saldos de tokens e os dados do contrato realmente ficam |
Cada bloco confirma o estado resultante por meio do stateRoot em seu cabeçalho. Os saldos são consultados com eth_getBalance(address, block), e o armazenamento de contratos por meio de eth_call (por exemplo, balanceOf de um token) ou eth_getStorageAt.
A diferença em relação ao modelo UTXO é fundamental:
| Pergunta | Blockchains UTXO | Blockchains baseadas em contas |
|---|---|---|
| Unidade de valor | Saídas discretas, gastas por inteiro | Um único saldo por endereço |
| Troco | Uma nova saída, muitas vezes para um novo endereço | Nenhum: o restante permanece no saldo |
| Vincular um pagamento de saída a um pagamento de entrada | Exato por saída; ambíguo dentro de uma transação com várias entradas | Nunca exato: todos os depósitos se misturam |
| Reutilização de endereço | Desaconselhada | Normal; um endereço por anos |
| Proteção contra repetição | Cada saída pode ser gasta uma única vez | Cada transação deve usar o próximo nonce |
Quando 10 ETH chegam a um endereço que já tem 50 ETH, nada nos dados indica quais ETH saíram em seguida; qualquer atribuição é uma convenção de rastreamento (consulte a aula Rastreando fundos para frente e para trás).
EOAs e contratos
Uma conta de propriedade externa (EOA) é controlada por uma chave privada e é o único tipo de conta que pode iniciar uma transação. Uma conta de contrato tem código e armazenamento, não pode iniciar nada por conta própria e só age quando chamada. eth_getCode(address, block) retorna 0x para uma EOA e o bytecode implantado para um contrato.
Três fatores tornam essa verificação menos simples do que parece:
- Temporalidade. O código só existe a partir do bloco em que o contrato foi criado. Os endereços podem ser calculados antes da implantação (o CREATE2 torna isso intencional), então um endereço sem código no bloco N pode ser um contrato no bloco N+1. Sempre verifique o código no bloco relevante.
- Destruição. Antes da atualização Dencun (março de 2024),
SELFDESTRUCTexcluía o código de um contrato. Desde a EIP-6780, isso só ocorre quando a função é chamada na mesma transação que criou o contrato; caso contrário, ela apenas transfere o saldo. - Delegação. Desde a atualização Pectra (maio de 2025), uma EOA pode conter o designador de delegação EIP-7702 de 23 bytes,
0xef0100, seguido de um endereço delegado. Uma regra ingênua do tipo "tem código, então é um contrato" a classifica incorretamente: a conta continua controlada por sua chave privada.
Portanto, um classificador robusto retorna três classes (EOA, contrato, EOA delegada) em determinado bloco, não duas.
O nonce é um presente para os analistas. Para uma EOA, ele equivale ao número de transações que ela enviou; portanto, um endereço com nonce 0 nunca enviou nada, e lacunas ou sequências rápidas no uso do nonce revelam padrões operacionais (consulte a aula Heurísticas do modelo de contas). Duas ressalvas: cada autorização EIP-7702 assinada por uma EOA também incrementa seu nonce, e o nonce de um contrato conta criações de contratos, começando em 1 segundo a EIP-161. Os endereços de contrato derivam do implantador: o CREATE usa o endereço e o nonce do implantador, e o CREATE2 usa o implantador, um salt e o hash do código de criação; por isso, os vínculos com o implantador são evidências fortes.
Estado versus histórico
Uma consulta de estado responde "o que este endereço tinha no bloco N?". O histórico responde "como chegou a esse estado?", e está distribuído por vários locais ao mesmo tempo:
- transações de nível superior (valor enviado, mais o gás pago pelo remetente);
- rastros de chamadas internas (valor transferido por contratos);
- logs (transferências de tokens e outros eventos);
- alterações de saldo que não são transações: taxas prioritárias creditadas ao destinatário de taxas do bloco, saques da camada de consenso creditados diretamente aos endereços desde abril de 2023 (EIP-4895: sem gás, sem execução de código, sem hash de transação), alocações de gênese e, antes de setembro de 2022, recompensas de mineração.
Nós completos mantêm apenas o estado recente; por isso, consultar o estado de blocos antigos exige um nó de arquivo ou um provedor que ofereça esse serviço (consulte a aula APIs de nós e acesso a dados). A próxima aula, Reconstruindo saldos e históricos, mostra como reconstruir um saldo a partir desses elementos e reconciliá-lo com o estado.
Transações internas
No protocolo, uma transação é apenas a mensagem de nível superior assinada. Quando um contrato encaminha ETH durante a execução, isso é uma chamada de mensagem: ela não tem hash, recibo nem log, a menos que o código emita um. Os exploradores as chamam de "transações internas", um rótulo conveniente, mas enganoso.
Considere um saque de uma carteira de contrato. A transação do usuário envia 0 ETH para o contrato da carteira 0x7c3E…12; durante a execução, o contrato chama 0xD4e5…3a com o valor 0xde0b6b3a7640000, que corresponde a 10^18 wei ou 1 ETH. A lista de transações de 0xD4e5…3a não mostra nada, mas seu saldo aumentou em 1 ETH. Somente um rastro (consulte a aula Transações, recibos e logs brutos do Ethereum) explica a alteração. Chamadas internas revertidas não transferem nada e devem ser excluídas.
As movimentações de tokens são diferentes: uma transferência ERC-20 é uma alteração no armazenamento do contrato do token, anunciada por um evento Transfer, não uma transação interna (consulte a aula Lendo transferências de tokens).
Contas inteligentes e abstração de contas
Uma conta inteligente é uma carteira implementada como contrato, com regras como múltiplos signatários, limites de gastos, recuperação ou patrocínio de gás. Três designs são importantes para a análise.
Carteiras de contrato (carteiras multisig são o caso clássico) mantêm fundos em um endereço de contrato. Os proprietários assinam fora da blockchain e um deles, ou um retransmissor, envia a transação. O agente econômico é o contrato; a EOA que enviou a transação pode ser apenas o último signatário.
A ERC-4337 adiciona abstração de contas sem alterações no protocolo. Os usuários assinam uma UserOperation (cujos campos incluem sender, nonce, callData, limites de gás, paymaster e signature) e a enviam a um mempool separado. Um bundler agrupa muitas UserOperations em uma transação que chama handleOps em um contrato EntryPoint singleton, que valida e executa cada uma e paga o bundler com o depósito da conta ou de um paymaster. Para cada operação, ele emite:
UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed)
As consequências são concretas: o from da transação é o bundler, uma transação pode conter operações de usuários sem relação entre si, o recibo abrange todo o lote e o agente real é o sender do evento. Uma consulta que lista contas inteligentes e seus patrocinadores de gás a partir de logs brutos:
-- Uma linha por UserOperation ERC-4337, com o bundler, a conta inteligente e o paymaster
SELECT
l.block_number,
l.tx_hash,
t.from_address AS bundler,
'0x' || SUBSTR(l.topic2, 27, 40) AS smart_account, -- remetente indexado
'0x' || SUBSTR(l.topic3, 27, 40) AS paymaster -- endereço zero = nenhum
FROM logs l
JOIN transactions t ON t.hash = l.tx_hash
WHERE l.topic0 = '0x49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f'
AND l.address IN (SELECT address FROM entrypoint_contracts);
O valor de topic0 é o hash Keccak-256 da assinatura do evento. Os endereços indexados ficam em tópicos de 32 bytes, preenchidos com zeros à esquerda; portanto, o endereço corresponde aos últimos 40 caracteres hexadecimais. SUBSTR(topic, 27, 40) pula 0x e os 24 caracteres de preenchimento. Alguns mecanismos chamam a função de SUBSTRING, e alguns armazenam os tópicos como dados binários, caso em que é preciso fatiar os bytes. Restringir a consulta a endereços de EntryPoint conhecidos (um por versão) evita encontrar eventos semelhantes emitidos por outros contratos.
A EIP-7702 permite que uma EOA existente adote o comportamento de uma conta inteligente. Uma transação do tipo 4 contém autorizações [chain_id, address, nonce, y_parity, r, s]; cada uma define o código do signatário como o designador de delegação, que persiste até ser substituído ou removido, e uma autorização com chain_id 0 é válida em todas as blockchains. O endereço mantém seu histórico e sua chave, mas agora pode agrupar chamadas ou ter o gás pago por terceiros. Os destinos de delegação também são evidências: um painel público on-chain publicado pela empresa de trading Wintermute em junho de 2025 constatou que mais de 80% das primeiras delegações apontavam para cópias de um único contrato "varredor", que esvazia carteiras cujas chaves foram vazadas.
Quem assina versus quem paga
| Padrão | Quem autoriza | from da transação (paga o gás) | Onde encontrar o agente real |
|---|---|---|---|
| Transação simples de EOA | Chave da EOA | A mesma EOA | from |
| Carteira de contrato | Assinaturas dos proprietários nos dados da chamada | Um proprietário ou retransmissor | to (a carteira) e seus eventos |
| Metatransação (ERC-2771) | Assinatura do usuário | Um retransmissor por meio de um encaminhador confiável | Dados da chamada decodificados |
| ERC-4337 | Regras de validação da conta inteligente | Bundler, reembolsado pela conta ou pelo paymaster | UserOperationEvent.sender |
| EIP-7702 patrocinada | Autorização e conteúdo assinado da EOA | Um patrocinador | A EOA delegada chamada |
Nunca equipare quem paga o gás ao agente antes de identificar o padrão. O financiamento de gás continua sendo uma evidência útil, mas, sob patrocínio, pode apontar para um serviço em vez de um proprietário (consulte a aula Heurísticas do modelo de contas).
Foco no exame: os quatro campos da conta (nonce, balance, codeHash, storageRoot) e o significado do nonce para EOAs e contratos; por que é impossível rastrear moedas individualmente em um saldo compartilhado; classificar EOAs, contratos e EOAs delegadas pela EIP-7702 em determinado bloco, incluindo o designador0xef0100e o efeito da EIP-6780; alterações de saldo que não são transações, como saques da EIP-4895 e recompensas de taxas; transações internas como chamadas de mensagem visíveis somente em rastros; os papéis da ERC-4337 (UserOperation, bundler, EntryPoint, paymaster) e os campos deUserOperationEvent; extrair um endereço de um tópico indexado; distinguir quem assinou, quem pagou o gás e quem agiu.