Five Account Abstraction Audit Findings
Signature replay, paymaster draining, policy bypass, and implementation destruction findings from a Biconomy audit.
I reported all five of these findings as High severity in the Code4rena contest, but I do not know which ones ended up as Q or solo findings.
- Signature replay using
batchId - Signature replay on
VerifyingSingletonPaymaster - Draining paymaster ETH with a malicious sender
- Bypassing the sponsored transaction policy and draining the paymaster deposit
- Destroying the
SmartAccountimplementation contract
1. Signature replay using batchId
The Biconomy wallet used batchId to allow more than one nonce. This made it possible for multiple dapps to have their own nonces without interfering with each other’s transactions, which was a significant developer-experience improvement.
But the wallet did not put batchId into the signature. That made it possible to replay the same signature with a different batchId.
For example, a user signs a transaction that sends 1 ETH to B with batchId = 1 and nonce = 0. The same signature also works with batchId = 2, 3, 4, 5, and so on, each with nonce = 0.

2. Signature replay on VerifyingSingletonPaymaster
I had covered this in my first post about ERC-4337. An EIP-712 domain separator would have easily prevented contract replay and cross-chain replay.
3. Draining paymaster ETH with a malicious sender
This is my favorite finding and one that anyone building on ERC-4337 should notice. The paymaster and account are owned by different entities, and the account is upgradeable, so you cannot guarantee that the sender will act as expected.
Nonce increments are not guaranteed, so a user can replay a transaction to attack the paymaster. You also cannot guarantee that the intended contract will be called, so “sponsor transactions for a specific contract” is not an option. This leads to the fourth finding.
4. Bypassing sponsored transaction policy
I discovered this issue by asking the Biconomy team how they used VerifyingPaymaster.
When auditing, ask many questions. No question is stupid.
I assumed the policy was set off-chain through an API, for example by allowing up to 1 ETH daily. It was easy to bypass that policy by withholding the transaction. This could be fixed by adding usernonce, which prevents a user from using the same nonce twice.

5. Destroying the SmartAccount implementation
The SmartAccount implementation contract could be destroyed, causing the classic Parity multisig freeze issue. An attacker needed to call init with an arbitrary address and take over. A similar but more complex and powerful vulnerability also existed in the eth-infinitism repository.