Back to Blog
Smart ContractsAccount AbstractionERC-4337DeFiWeb3

Account Abstraction (ERC-4337) Security: The New Attack Surface Nobody's Auditing

April 13, 20267 min readRedVolt Team

Account abstraction has quietly become one of the fastest-growing primitives in Ethereum. Safe, Biconomy, ZeroDev, Alchemy AA, and a dozen rollup-native wallet stacks now push billions of dollars in volume through ERC-4337 infrastructure every month. And yet, when we audit these systems, we keep finding the same classes of bugs — most of them introduced by teams who assumed a smart wallet is "just a contract."

It isn't. ERC-4337 introduces four new trust boundaries — the EntryPoint, the bundler, the paymaster, and the user's own signature scheme — and every one of them is exploitable in ways that traditional Solidity audits don't check for.

Why ERC-4337 Breaks Your Threat Model

Before account abstraction, a wallet transaction had exactly one trust path: the user signs, the EOA pays gas, the transaction executes. The signature was the authorization. Everything else was downstream of it.

ERC-4337 blows that model apart. A single UserOperation now touches:

01

The sender contract

Your smart account — which may use a signature scheme you wrote yourself (ECDSA, WebAuthn, passkeys, social recovery, session keys)

02

The EntryPoint

A singleton contract that validates and executes your op — shared infrastructure you don't control

03

The bundler

An off-chain relay that picks which UserOps to include and can front-run, censor, or griefing-attack you

04

The paymaster (optional)

A third-party contract that may sponsor your gas — creating a new execution path that can be abused to drain funds or replay ops

Each of these is a place where a real attacker has already stolen real money. Most Solidity-focused audits skip at least two of them.

The Bugs We Keep Finding

Over the last six months of auditing AA wallets and paymaster systems, here are the recurring classes of vulnerability — ranked by how often they appear in the wild.

1. Paymaster Post-Op Grief Attacks

A paymaster sponsors gas for a UserOp. The EntryPoint calls validatePaymasterUserOp() before execution and postOp() after. Most teams correctly check signatures in validate, but they treat postOp as a simple accounting callback — and they forget it runs after the UserOp has already consumed gas from the paymaster's deposit.

⚠️The attack

If postOp reverts, the EntryPoint will retry it once in "postOpReverted" mode — but the original UserOp's gas has already been paid. An attacker who can force postOp to revert (e.g. by manipulating an oracle read the paymaster depends on, or triggering an ERC-777 hook) can drain the paymaster's deposit one op at a time.

We've found this class of bug in three separate production paymasters in 2026 alone. The fix is straightforward — make postOp failure-safe — but the bug is easy to miss because it requires reasoning across two execution phases.

2. Session Key Over-Permissioning

Session keys are one of the best UX features in AA: a user can authorize a dApp to act on their behalf within narrow limits (spend no more than $50 of USDC, only to contract X, only for 24 hours). The implementation is usually a validator contract that checks the session key's scope before allowing execution.

The bug we see repeatedly: the scope check is on the target contract, not on the effect.

A session key authorized to call router.swap() on Uniswap v3 looks bounded. But router.multicall() lets the session key chain arbitrary calldata into the same target. If the validator only whitelists the target address, the session key can now call approve(attacker, MAX_UINT) through the multicall — and drain the wallet.

Real session-key implementations must:

  • Decode and inspect the inner calldata, not just the outer selector
  • Reject multicall, aggregate, and any function that forwards arbitrary calls to the same contract
  • Enforce per-token spending limits at the ERC-20 transfer event, not at the function call site

3. Signature Replay Across Chains

When you sign a UserOp, the hash that gets signed includes chainId — in theory. In practice, about 30% of the smart wallet implementations we audit either hash the UserOp before appending chainId, or derive chainId from a mutable state variable instead of block.chainid.

If your signature doesn't bind to the actual chain at execution time, an attacker can take a UserOp you signed on Ethereum mainnet, replay it on Base or Arbitrum (assuming you've deployed the same wallet address there — and if you use CREATE2 with the same salt, you have), and execute the same transaction with your authority on a chain where your balance is different.

ℹ️How to check

Grep your signature-hashing code for block.chainid. If it's not in the hash, you have a replay bug. If it is, verify it's read fresh on every validation call — not cached in storage where a malicious implementation upgrade could overwrite it.

4. Bundler Censorship → User Griefing

This one isn't a contract bug — it's an infrastructure-level attack — but it shows up in audits because teams often write UserOps that assume inclusion. A bundler can:

  • Drop your UserOp silently
  • Include it on a chain where it will revert (wasting your deposit)
  • Reorder your ops to front-run a price-sensitive one

The defensive pattern is to use a ValidUntil timestamp in every UserOp and to verify off-chain that the bundler you're relying on has a reputation score (rundler, alto, and skandha all expose this). Contract-side, your UserOp logic must not assume ordering — if a second op can arrive before a first, design for it.

What an AA-Aware Audit Looks Like

When RedVolt's smart contract audit engine runs against an ERC-4337 wallet, our agents test specifically for these AA-native attack patterns:

1

Signature hash coverage

Parse the signature scheme, confirm every field that affects execution (chainid, entrypoint, nonce, validUntil) is included in the hash

2

Paymaster post-op safety

Simulate every revert path in postOp — oracle failures, token hooks, re-entrancy — and confirm the paymaster's deposit is protected

3

Session key scope enforcement

Generate adversarial calldata for every whitelisted target and verify the validator rejects calls that escape the intended scope

4

Cross-chain replay

Compute the UserOp hash across chain IDs and verify the signature binds to the executing chain

5

Upgrade path

Check if the account's implementation is upgradeable — and if so, whether the upgrade itself is gated by a signature check that matches the current owner

Every finding comes with a Foundry PoC that demonstrates the exploit against a fork of the deployed contract. If we can't write a PoC that passes, we don't ship the finding.

The Takeaway

Account abstraction is too useful to skip. Smart wallets are going to carry the next wave of mainstream Ethereum users, and the infrastructure around them — paymasters, session keys, bundlers — will keep expanding. But every new primitive is a new attack surface, and the audit industry is still catching up.

If you're building on ERC-4337, three concrete things you can do this week:

  1. Run a RedVolt smart contract audit on your wallet + paymaster + any custom validators. We test for all four bug classes above by default.
  2. Read the ERC-4337 audit reports from OpenZeppelin and Spearbit for your specific stack — and compare their scope to yours.
  3. Add fork tests for cross-chain replay to your CI. If a UserOp signed on mainnet executes on Base in your tests, you have a bug.

Account abstraction is going to be the standard in two years. Audit it like it's already production-critical — because for a growing number of users, it already is.


Need an audit for your ERC-4337 stack? Request a smart contract audit — we'll cover every trust boundary, not just the contract itself.

Want to secure your application or smart contract?

Request an Expert Review