Part III · Chapter 31 of 43 · Application layer

EIP-4337: account abstraction without touching the protocol

EOAs are rigid: one key, gas only in ETH, one action at a time. Account abstraction makes accounts programmable — and EIP-4337 pulls it off with zero consensus changes, using a higher-layer transaction, a separate mempool, bundlers, and a singleton EntryPoint.

Updated Jun 23, 2026 · 14 min
Assumed
  • EOAs vs contracts
  • the mempool

There are two kinds of Ethereum account: a contract (programmable, but it can’t start anything — it only runs when called) and an externally-owned account (an EOA — it can start transactions, but it’s rigid). Everything you do begins from an EOA, and an EOA is stuck with one signing key, gas paid only in ETH, and one action per transaction. People wanted accounts that are programmable — multisig, passkeys, social recovery, batching, letting someone else pay your gas. That’s account abstraction. The obvious way to get it is to change the protocol so accounts can be contracts with their own rules — a hard fork, years of coordination. EIP-4337 asks a sharper question: can we get all of it with zero consensus changes? Let’s derive how.

1 step The rigid EOA

The problem: the EOA is a straitjacket

Every transaction originates from an EOA, and an EOA can only do exactly what the protocol hard-codes. Its validity rule is fixed: one valid secp256k1 signature over the transaction, the right nonce, and enough ETH. That single rule rules out almost everything people want.

an EOA is rigid — extra powers bounce off EOA 1 key · 1 action multisig passkey pay in USDC batch social recovery
An EOA's rules are fixed: one ECDSA key, gas in ETH, one action per transaction. Multisig, passkeys, paying gas in USDC, batching, social recovery — every wish bounces off.

One key means losing it loses everything — no multisig, no hardware passkeys, no social recovery. Gas only in ETH means you must pre-hold ETH to do anything — no sponsor, no paying in USDC. One action per transaction means approve then swap is two signatures, two fees. A contract account could encode any rule you like ( account abstraction Letting an account's validity be defined by its own code — any signature scheme, any gas policy, batching — instead of the protocol's one fixed ECDSA-and-ETH rule. ) — but a contract can’t initiate a transaction; it only executes when something calls it.

→ Step 2: invent a transaction that lives one layer up.

2 step A UserOperation

A higher-layer transaction: the UserOperation

Don’t touch what a transaction is. Add a new object one layer above it: a UserOperation A 4337 struct describing what a smart account wants to do — the account, the calldata, gas limits, and a signature the account itself will verify with whatever scheme it likes. Not an Ethereum transaction; it travels in a separate mempool. . It describes what a smart account wants done — the account address, the callData (the action, which may be a batch), gas limits, and a signature the account itself will check however it likes. The user signs it with whatever scheme their account uses — an ECDSA key, a phone’s passkey, a 2-of-3 multisig — and broadcasts it to a separate, alternative mempool just for UserOperations, distinct from the regular transaction mempool.

a signed UserOperation rides its own mempool smart account (contract) ✗ can’t start its own tx UserOperation signed · what you want UserOp mempool a separate lane regular tx mempool
A smart account can't send a transaction itself, so you sign a UserOperation — a higher-layer object — and broadcast it to its own mempool, separate from the regular transaction mempool. No consensus change: just a new data shape and a new gossip network.

Nothing about consensus changed here. A UserOperation isn’t a transaction the protocol understands — it’s an application-layer message in a new peer-to-peer network. Which raises the obvious problem:

→ Step 3: have someone wrap it and run it.

3 step Bundlers & EntryPoint

Bundlers wrap them; the EntryPoint runs them

Enter the bundler An ordinary node (an EOA) that watches the UserOperation mempool, packs a batch of UserOps into one normal transaction to the EntryPoint, fronts the L1 gas, and is reimbursed from the accounts' deposits. : an ordinary node — anyone can run one — that watches the UserOp mempool, picks a batch, and wraps them into one normal Ethereum transaction. It sends that transaction to a singleton EntryPoint A single audited contract (one per network) that 4337 routes everything through. Its handleOps loops over each UserOp doing validation then execution, and accounts/paymasters trust only it. contract, which loops over each UserOp in two strictly-separated phases:

  1. Validation — the EntryPoint calls the account’s validateUserOp(...), which runs whatever custom logic the account defines (verify a passkey signature, a multisig threshold, a session key) and must agree to pay.
  2. Execution — the EntryPoint calls the account with the UserOp’s callData — the actual action, which can bundle several calls into one.
a bundler packs many UserOps into one tx UserOp UserOp UserOp bundler packs a batch 1 tx EntryPoint for each UserOp validate → execute
A bundler (an EOA) collects UserOps and wraps them into a single transaction to the singleton EntryPoint, which validates (running each account's own logic) then executes each — fronting the gas and getting reimbursed by the accounts.

The bundler fronts the L1 gas and is reimbursed by the EntryPoint out of each account’s prefunded deposit. So why doesn’t it get cheated into including a UserOp that fails to pay? It simulates each UserOp’s validation off-chain first, and the rules forbid validation from reading other accounts’ storage — so a UserOp can’t change its own validity based on state a different transaction might move, and the simulation stays truthful right up to inclusion.

→ Step 4: let a third party pick up the bill.

4 step Paymasters

Paymasters: someone else pays, or pay in any token

Add one optional party: a paymaster contract. A UserOperation can name a paymaster that agrees to cover its gas. That unlocks two things people really wanted. A dapp can sponsor your transactions — you hold no ETH at all and it just works. Or a paymaster can let you pay gas in an ERC-20 like USDC: it pulls the token from you and pays the ETH gas on your behalf. The EntryPoint settles up at the end and reimburses the bundler from the paymaster’s (or the account’s) deposit.

a paymaster sponsors the gas your UserOppay in USDC? EntryPoint paymasterpays ETH gas reimburse bundler reimbursed
A paymaster can sponsor your gas entirely, or accept payment in any token and cover the ETH itself. The EntryPoint settles accounts and reimburses the bundler — so you can transact with no ETH.
04 Go Deeper Where to take it from here