Account abstraction parte 4: assinaturas agregadas
Escrito por David Philipson
Aggregate signatures
Nossa implementação atual valida cada user op do bundle separadamente. Essa é uma forma bem direta de pensar a validação, mas potencialmente custosa. Verificar assinaturas pode acabar ficando caro em termos de gas, porque isso exige bastante aritmética criptográfica.
Não seria bom se pudéssemos validar vários ops ao mesmo tempo com apenas uma assinatura em vez de várias?
Fazer isso depende de um conceito da criptografia, assinaturas agregadas.
Um esquema de assinatura que suporta agregação oferece uma forma, dadas várias mensagens assinadas com chaves diferentes, de gerar uma única assinatura combinada tal que verificar a assinatura combinada implica que todas as assinaturas que a compõem também são válidas.
Um exemplo comum de esquema de assinatura que suporta agregação é BLS.
Essa otimização é particularmente útil para implementar rollups, já que o objetivo principal de um rollup é a compressão de dados, e a agregação de assinaturas nos permite comprimir a parte referente às assinaturas.
Para saber mais sobre a economia de espaço obtida com a agregação de assinaturas, veja o tweet do Vitalik sobre o assunto.
Apresentando os aggregators
De imediato, percebemos que nem todos os user ops de um bundle podem ter suas assinaturas agregadas juntas. Lembre-se de que uma wallet tem permissão para usar qualquer lógica arbitrária que quiser para validar a assinatura que recebe, então pode haver vários esquemas de assinatura presentes no mesmo bundle.
Como provavelmente não podemos agregar assinaturas de esquemas diferentes, nosso bundle acabará com grupos de ops, cada grupo usando um esquema de agregação distinto ou nenhum esquema de agregação.
Como precisamos ter vários esquemas de agregação representados on chain, cada um com sua própria lógica, cada esquema de agregação será representado por um contrato que chamaremos de aggregator.
Um esquema de agregação é definido por como ele combina várias assinaturas em uma só e por como ele valida a assinatura combinada, então um aggregator expõe essas duas funções como métodos:

Como cada wallet define seu próprio esquema de assinatura, cabe a cada wallet decidir com qual aggregator ela é compatível, se houver algum.
Se uma wallet quiser participar da agregação, ela expõe um método para escolher seu aggregator:
Usando esse novo método getAggregator, o bundler pode agrupar ops que têm o mesmo aggregator e usar o método aggregateSignatures desse aggregator para calcular uma assinatura combinada para eles.
Um grupo poderia se parecer com isto:
💡 Se um bundler tiver conhecimento off-chain sobre um aggregator em particular, ele pode otimizar codificando de forma nativa uma versão do algoritmo de agregação de assinaturas, em vez de executar aggregateSignatures como código EVM.
Em seguida, precisamos atualizar o contrato entry point para usar os novos aggregators.
Lembre-se de que o entry point tem um método handleOps que recebe uma lista de ops.
Vamos dar a ele um novo método, handleAggregatedOps, que faz a mesma coisa, mas recebe os ops agrupados por aggregator:
O novo método, handleAggregatedOps, funciona basicamente da mesma forma que handleOps. A única diferença está na etapa de validação.
Enquanto handleOps realiza a validação chamando o método validateOp de cada wallet, handleAggregatedOps vai, em vez disso, chamar o método validateSignatures do aggregator sobre a assinatura combinada de cada grupo, usando o aggregator daquele grupo.

Estamos quase terminando!
Mas há um problema aqui que já deve ser bem familiar a essa altura.
O bundler quer simular a validação e verificar que o aggregator vai validar um grupo de ops antes de incluí-los no bundle, porque, se a validação falhar, o bundler é obrigado a pagar pelo gas. Mas um aggregator com lógica arbitrária pode facilmente ter sucesso durante a simulação e falhar durante a execução.
Vamos resolver isso exatamente da mesma forma que fizemos para paymasters e factories: restringimos a quais storage o aggregator pode acessar e quais opcodes ele pode usar, e exigimos que ele faça stake de ETH no entry point, a menos que não acesse storage.
E é isso para assinaturas agregadas!
Encerramento
O que criamos aqui é mais ou menos a arquitetura completa do ERC-4337! Existem algumas diferenças nos detalhes, como os nomes e argumentos de alguns dos métodos, mas não sobra nada que eu consideraria uma diferença arquitetural. Se eu fiz um bom trabalho, você agora deve conseguir ler o ERC-4337 de verdade e entender o que está acontecendo.
Se você chegou até aqui, muito obrigado por ler minha explicação! Espero que ela tenha te ajudado tanto quanto me ajudou escrevê-la.
Adendo: diferenças em relação ao ERC-4337
Embora já tenhamos a arquitetura geral da account abstraction definida, as pessoas inteligentes por trás do ERC-4337 pensaram em algumas coisas ligeiramente diferentes do que descrevemos acima.
Vamos ver algumas delas!
1. Intervalos de tempo de validação
Acima, fui bem vago sobre o tipo de retorno do validateOp da wallet e do validatePaymasterOp do paymaster. O ERC-4337 encontra uma boa forma de aproveitar isso.
Algo que uma wallet gostaria muito de fazer é permitir que um user op seja válido apenas por um certo período de tempo. Caso contrário, um bundler mal-intencionado poderia segurar essa operação por muito tempo e depois incluí-la em um bundle bem mais tarde, num momento vantajoso para o bundler.
A wallet poderia querer se proteger disso verificando o TIMESTAMP durante a validação, para garantir que ele não esteja muito distante no futuro, mas não pode, porque proibimos o TIMESTAMP durante a validação para evitar que as simulações fiquem imprecisas. Isso significa que a wallet precisa de outra forma de indicar em quais momentos a operação é válida.
Assim, o ERC-4337 dá a validateOp** um valor de retorno que a wallet pode usar para escolher um intervalo de tempo:**
Esse valor de retorno representa o intervalo de tempo em que a operação é válida como dois inteiros de 8 bytes, um após o outro.
Outra observação do ERC-4337: as wallets devem retornar um valor sentinela do validateOp em vez de reverter em caso de falha na validação, o que ajuda na estimativa de gas, já que o eth_estimateGas não informa quanto gas foi usado em uma transação que reverte.
2. Call data arbitrário para wallets e factories
Dissemos que a interface da nossa wallet era:
No ERC-4337, as wallets não têm de fato um método chamado executeOp.
Em vez disso, a user operation tem um campo callData:
Isso é passado para a wallet como call data.
Para um contrato inteligente típico, os quatro primeiros bytes desses dados serão interpretados como um function selector e o restante como argumentos da função.
Isso significa que, além do método validateOp obrigatório, as wallets podem definir sua própria interface, e as user operations podem ser usadas para chamar métodos arbitrários na wallet.
Na mesma linha, no ERC-4337 os contratos factory não têm de fato um método deployContract. Eles também recebem call data arbitrário, nesse caso a partir do campo initCode do op.
3. Dados compactos para paymasters e factories
Acima, dissemos que a user operation continha campos para especificar um paymaster, assim como quais dados passar para ele:
No ERC-4337, esses campos são combinados em um só como uma otimização, em que os primeiros 20 bytes do campo são o endereço do paymaster e o restante são os dados:
O mesmo vale para as factories e os dados enviados a elas: enquanto usamos dois campos, factory e factoryData, o ERC-4337 combina esses em um único campo, initCode.
Pronto, você conseguiu!
Esperamos que você tenha aprendido bastante sobre Account Abstraction.
Você poderia ter inventado a account abstraction
Perdeu o início dessa série de 4 partes? Volte e leia desde o começo!
Visões gerais relacionadas
Carteiras2 de setembro de 2026
Agent wallets: o modelo de sessão e permissões para agentes de IA
Como agentes de IA obtêm acesso a wallets com escopo definido e revogável, sem manter chaves privadas: sessions, delegated signing e revogação instantânea.
Carteiras29 de julho de 2026
Pare de colar chaves privadas no Cursor: como dar uma wallet ao seu coding agent
Dê ao seu coding agent uma wallet sem dar a chave. Como as agent wallets do Alchemy CLI usam sessões com escopo definido para que agents transacionem sem private keys no .env.
Carteiras24 de junho de 2026
O que é um crypto bundler?
Um crypto bundler combina múltiplas transações ou operações em um único envio onchain, abrangendo batching, MEV, rollups, lançamentos de tokens e account abstraction.

Construa magia blockchain
A Alchemy combina os produtos e ferramentas de desenvolvimento Web3 mais poderosos com recursos, comunidade e suporte lendário.