Back to Blog
ERC-4337 Smart Accounts: Six Failure Modes We're Already Seeing in Audits
AuditSolidityWeb3 Security

ERC-4337 Smart Accounts: Six Failure Modes We're Already Seeing in Audits

13 min
Account abstraction was supposed to simplify user experience. And it does — but it transfers the security burden from a single cryptographic primitive (the private key) onto a programmable system that most teams are not equipped to audit correctly.
Trail of Bits published their breakdown of six mistake categories in ERC-4337 smart accounts this week. The patterns they identified align with what we're encountering in the field. This post goes beyond the taxonomy — we're going to show you what these failures look like in production code, why they compound each other, and what your team needs to do before you ship any account abstraction logic.

Why ERC-4337 Changes the Security Equation

Traditional EOA wallets have one rule: control the private key, control the account. It's blunt, inflexible, and from a security standpoint, it's predictable.
ERC-4337 replaces that with a validateUserOp function on your account contract. That function is now the trust boundary. Every assumption downstream — that the caller is authorized, that the nonce is valid, that the paymaster isn't being abused — flows from whatever logic you write there.
This is the core problem: a system that was previously secured by cryptography is now secured by code. And code has bugs.
The EVM execution environment doesn't care whether your validateUserOp is logically sound. It will execute whatever you wrote. The bundler will forward the UserOperation. The EntryPoint will call your account. And if you got something wrong, it will be exploited.

The Six Failure Modes

1. Signature Validation Without Replay Protection

The most basic mistake: validating a signature without binding it to a nonce or chain ID. We see this when teams port EOA signature schemes directly into validateUserOp without accounting for the new execution context.
1// Vulnerable — no chainId or nonce binding
2function validateUserOp(
3 UserOperation calldata userOp,
4 bytes32 userOpHash,
5 uint256 missingAccountFunds
6) external returns (uint256 validationData) {
7 bytes32 hash = keccak256(abi.encode(userOp.callData));
8 address recovered = ECDSA.recover(hash, userOp.signature);
9 if (recovered != owner) return SIG_VALIDATION_FAILED;
10 return 0;
11}
An attacker who captures a valid UserOperation on Arbitrum can replay it on mainnet if the same account is deployed at the same address (common with CREATE2). The nonce is checked by the EntryPoint, but only if your implementation correctly increments it — and only against the same EntryPoint on the same chain.
The fix is to use userOpHash directly (which already includes chainId and EntryPoint address) rather than re-hashing callData independently.

2. Paymaster Logic That Can Be Gamed

Paymasters sponsor gas. That sentence alone should trigger a threat modeling session. Any contract that agrees to pay for other people's operations has an obvious economic attack surface.
The failure pattern here is paymasters that validate sponsorship intent without enforcing execution constraints. A paymaster might check "is this user on our allowlist" at validatePaymasterUserOp time, then have no enforcement at postOp time that the actual callData matched what was expected.
Result: whitelisted users submitting unexpected call data, potentially draining the paymaster's deposit in the EntryPoint.

3. Incorrect Handling of the Validation Return Value

validateUserOp returns a uint256 packed with a time range (validAfter, validUntil) and a signature validation status bit. This packing is non-obvious and teams routinely return raw error codes that the EntryPoint interprets as time-bounded validity windows.
Returning 1 doesn't mean "invalid" from the EntryPoint's perspective in all contexts — it means "valid but expired" depending on how the bits are set. We've seen implementations that intended to reject operations but inadvertently packed return values the EntryPoint treats as valid.
The EntryPoint's _validateAccountAndPaymasterValidationData extracts these fields with bitmasking. Your return value must be constructed with the _packValidationData helper or equivalent, not returned as a raw success/failure integer.

4. Module Systems Without Isolation Boundaries

ERC-4337 accounts increasingly use plugin/module architectures — validation modules, execution modules, fallback handlers. The promise is composability. The risk is that one malicious or buggy module can compromise the entire account.
This mirrors the proxy pattern vulnerabilities we documented in our upgrade patterns security guide: the account becomes a trust aggregator, and the security of the aggregate equals the security of its weakest installed component.
The specific failure: module installation functions that don't enforce access control. If installModule(address module) can be called by anyone, an attacker calls it with a module that overrides validateUserOp to return success for any signature.
1// Vulnerable — no access control on module installation
2function installModule(address module, bytes calldata initData) external {
3 IModule(module).onInstall(initData);
4 _modules[module] = true;
5}

5. Storage Layout Violations in the Validation Phase

The ERC-4337 spec restricts which storage slots a validateUserOp function can access during bundler simulation. These restrictions exist to prevent simulation-grief attacks — operations that appear valid during simulation but fail on-chain because another transaction modified shared state between simulation and execution.
Specifically, validateUserOp cannot read from storage slots that are not associated with the account's own address or the sender's UserOperation. Reading from arbitrary global state (shared price oracles, third-party registries) violates these constraints and will cause bundlers to drop your operations.
The irony is that this restriction is often discovered only in production when operations inexplicably fail to land on-chain. Bundlers don't always surface clear error messages about storage access violations.

6. Social Recovery Logic With Griefing Vectors

Social recovery is one of ERC-4337's most compelling features and one of its most consistently botched implementations. The failure isn't usually a direct theft — it's a griefing mechanism that can lock a user out of their account permanently.
Recovery schemes that allow any guardian to initiate recovery (but require threshold approval to complete) create a window where an adversarial guardian can spam initiation transactions, resetting the recovery timer and preventing legitimate recovery from completing. If your recovery module uses a recoveryInitiatedAt timestamp with a fixed window, a single malicious guardian can prevent recovery indefinitely at the cost of gas.

The Compounding Problem

These six failure modes rarely appear in isolation. The real danger is how they interact.
A paymaster with lax validation (failure mode 2) combined with a module system without isolation (failure mode 4) means a whitelisted user can install a malicious module, use the paymaster to sponsor that module's installation gas, and then execute arbitrary calls from an account the team assumed was locked down.
This is why threat modeling for smart accounts cannot be done contract-by-contract. You need to model the full operation lifecycle: UserOperation construction → bundler simulation → EntryPoint validation → account execution → paymaster post-op.

What the Bundler Doesn't Protect You From

A misconception we encounter frequently: teams assume the bundler and EntryPoint act as a security layer. They don't — they act as an execution layer that enforces the ERC-4337 protocol rules, not your application's business logic.
The EntryPoint will faithfully execute a UserOperation that passes validateUserOp even if the operation drains the account, installs a malicious module, or transfers ownership to an attacker. The EntryPoint's job is protocol conformance. Security is your job.
This maps directly to the defense in depth principle: the infrastructure gives you a framework, not a guarantee. Every layer you own must be independently secure.

Audit Checklist for ERC-4337 Implementations

Before submitting your smart account implementation for audit — or deploying it — run through these:
Validation phase:
  • Is userOpHash used directly for signature binding, or are you re-constructing a hash that omits chain ID or EntryPoint address?
  • Does validateUserOp access any storage not owned by the account address? Test bundler simulation explicitly.
  • Is the return value constructed with proper bit packing for time ranges?
Paymaster:
  • Is the sponsorship condition enforced at both validation and post-op stages?
  • Can a whitelisted user submit arbitrary callData and still get sponsored?
  • What happens if the paymaster deposit is drained? Graceful degradation or silent failure?

Are you audit-ready?

Download the free Pre-Audit Readiness Checklist used by 35+ protocols preparing for their first audit.

No spam. Unsubscribe anytime.

Module system:
  • Does module installation require owner authorization?
  • Can a module override core validation logic?
  • Are there reentrancy vectors between the account and modules during execution?
Recovery:
  • Can a single guardian grief the recovery process?
  • Is there a time-lock on ownership changes that gives the legitimate owner time to respond?
  • What's the behavior if recovery is initiated while a previous recovery is in progress?

The Bigger Picture: AI Agents and Smart Accounts

This week also saw Trail of Bits publish on agentic browser isolation failures — and the overlap with smart account security is not coincidental.
AI agents are increasingly being wired to ERC-4337 smart accounts as their on-chain execution layer. The agent sends UserOperations, the smart account validates and executes them. This creates a new threat surface: if the agent can be manipulated via prompt injection (a demonstrated attack vector against agentic browsers), the attacker doesn't need to compromise the key — they need to compromise the agent's intent.
Validation logic that assumes "if the signature is valid, the intent is authorized" breaks down entirely in an agent context. We expect this to become a major audit focus category in 2026.
For teams building agent-controlled accounts: validation must constrain not just signature authenticity but operation semantics. Spending limits, call target allowlists, and execution rate limits belong in validateUserOp or in a dedicated execution module — not as an afterthought in your agent's system prompt.

Actionable Takeaways

  1. Audit your validateUserOp return value construction. If you are not using the EntryPoint's _packValidationData helper or have not explicitly tested your return values against the EntryPoint's unpacking logic, you have untested code in your trust boundary.
  2. Run bundler simulation with a real bundler before mainnet. Locally, your operations pass. A compliant bundler running storage access validation may reject them silently. Use eth_estimateUserOperationGas against a production bundler endpoint during testing.
  3. Treat module installation as a privileged operation. Every installed module is effectively an extension of your trust boundary. Review its validateUserOp implementation as carefully as your own.
  4. Model your paymaster's worst-case economics. What does it cost an attacker to drain your paymaster deposit? If the answer is "less than the deposit," you need additional constraints.
  5. If you're building agent-controlled accounts, get a dedicated audit. The combination of programmable validation and external intent generation is a new attack surface. Checklists written for human-controlled smart accounts are not sufficient.

If you're shipping ERC-4337 smart account infrastructure — whether as a wallet SDK, a protocol's session key system, or an agent execution layer — contact us for an audit before you finalize your deployment. The security retainer model works particularly well for teams iterating on account logic post-launch: continuous review as your module registry grows, not a one-time snapshot.

About Zealynx Security

ERC-4337 smart accounts are powerful, but the programmable validation surface they introduce demands audit expertise that goes beyond traditional smart contract review. At Zealynx Security, we audit the full UserOperation lifecycle: account validation, paymaster logic, module systems, and recovery flows.
Building or integrating account abstraction? Get the full execution pipeline reviewed before deployment. Request an EVM audit scope ->
References:

FAQ

1. What is ERC-4337 account abstraction?
ERC-4337 is an Ethereum standard that replaces traditional externally owned accounts (EOAs) with programmable smart contract wallets. Instead of a single private key controlling an account, the account's validation logic is defined in code -- enabling features like multi-sig, social recovery, spending limits, and gasless transactions via paymasters.
2. Why is ERC-4337 harder to secure than a regular smart contract?
Traditional smart contracts have a defined set of entry points. ERC-4337 introduces a multi-component execution pipeline -- the account, the bundler, the EntryPoint, the paymaster, and optional modules -- each with its own trust assumptions. A vulnerability in any component can compromise the entire account, and these interactions are harder to reason about than a standalone contract.
3. What is a UserOperation and how does it differ from a transaction?
A UserOperation is a struct that describes an intent (similar to a transaction) but is not submitted directly to the blockchain. Instead, it is sent to a bundler, which packages multiple UserOperations into a single on-chain transaction via the EntryPoint contract. The key difference is that validation logic is programmable -- the smart account decides whether to accept the operation, not just a cryptographic signature check.
4. Can a paymaster be drained by malicious users?
Yes. If a paymaster validates sponsorship without constraining what operations it sponsors, attackers can craft UserOperations that consume maximum gas while doing nothing useful. The paymaster pays for the gas from its EntryPoint deposit, and repeated abuse can drain it entirely. Proper paymasters must validate operation calldata and enforce gas limits.
5. How do cross-chain replay attacks work on smart accounts?
When smart accounts are deployed at deterministic addresses using CREATE2, the same account address exists on multiple chains. If the signature validation does not bind to the specific chain ID, a valid UserOperation signed for one chain can be replayed on another. The fix is using the EntryPoint-provided userOpHash, which includes chain ID and EntryPoint address.
6. Should I audit my ERC-4337 account differently than a regular DeFi contract?
Absolutely. A standard DeFi audit reviews contract logic in isolation. An ERC-4337 audit must cover the full UserOperation lifecycle -- validation logic, return value packing, storage access restrictions during simulation, paymaster economics, module installation access control, and recovery flow griefing vectors. The bundler simulation model adds constraints that do not exist in traditional contract execution.

Glossary

TermDefinition
Account AbstractionA design pattern that replaces fixed EOA logic with programmable smart contract accounts, enabling custom validation, recovery, and gas payment mechanisms.
UserOperationA struct in ERC-4337 that encodes a user's intent, including calldata, gas limits, and signature, submitted to bundlers instead of directly to the blockchain.
BundlerAn off-chain actor that collects UserOperations, simulates them, and submits valid ones to the EntryPoint contract as a single on-chain transaction.
PaymasterA smart contract that sponsors gas for UserOperations, enabling gasless transactions for end users in exchange for alternative payment or whitelisting.
EntryPointThe singleton contract in ERC-4337 that orchestrates UserOperation validation, execution, and gas accounting across all smart accounts.
Social RecoveryA wallet recovery mechanism where designated guardians can collectively authorize ownership changes if the primary key is lost or compromised.
Session KeyA temporary, scoped key that delegates limited authority to a dApp or agent without exposing the primary account signer.

Are you audit-ready?

Download the free Pre-Audit Readiness Checklist used by 35+ protocols preparing for their first audit.

No spam. Unsubscribe anytime.

oog
zealynx

Smart Contract Security Digest

Monthly exploit breakdowns, audit checklists, and DeFi security research — straight to your inbox

© 2026 Zealynx