Sign in

Account abstraction

Every Ethereum account today is one of two things: an EOA controlled by a private key, or a contract account controlled by code. EOAs can initiate transactions but their behavior is fixed by the protocol. Contracts can have any behavior but cannot initiate transactions on their own. Account abstraction is the umbrella term for changing this. The goal is to let accounts be controlled by arbitrary code while still being able to send transactions. This lecture covers what AA is, the two production approaches today (ERC-4337 and EIP-7702), and the kinds of features they unlock: passkeys, social recovery, sponsored gas, batched operations, and session keys.

What's wrong with EOAs

An EOA is just a public key derived from a private key, with a balance attached to it. The protocol allows exactly one kind of authorization: a transaction signed by the matching private key, using ECDSA on the secp256k1 curve. That's it.

This works but it's restrictive in a long list of ways.

EOA vs smart account: what changes when code controls your account EOA (Externally Owned Account) controlled by a private key Signature scheme: ECDSA on secp256k1, period Gas payment: must hold ETH, no alternatives Lose the key: account is gone forever Multiple signers: not natively possible Batched operations: one tx, one action Spending limits, allowlists: no, key is all-or-nothing Initiate transactions: yes (this is the one win) Powerful but rigid cannot be customized Smart account controlled by contract code Signature scheme: whatever the code accepts passkeys, multisig, BLS, ZK proofs Gas payment: USDC, sponsored, paymaster Lose the key: social recovery via guardians Multiple signers: thresholds, weighted votes Batched operations: approve + swap + stake in one tx Spending limits, allowlists: session keys with scoped power Initiate transactions: needs help (the problem to solve) Flexible but can't self-initiate needs ERC-4337 or EIP-7702

A smart account is a contract that holds your funds and decides for itself what counts as a valid operation. The code can require two signatures from a 2-of-3 multisig. It can accept a passkey signature from your phone instead of an ECDSA signature. It can require a transaction below a daily spending limit to go through automatically while above-limit transactions wait for a second approver. It can rotate keys, recover access via trusted guardians, pay gas in any token. Anything you can express in Solidity.

The catch is the one thing in the right-hand column that's missing: a contract cannot initiate a transaction. Only an EOA can. Without something to bridge the two sides, smart accounts are still passive, they wait to be called. Account abstraction is the work of building that bridge.

Two productions approaches exist today. ERC-4337 is an application-layer solution that went live on Ethereum mainnet in March 2023. It works without any consensus change. EIP-7702 is a protocol-layer change that activated in the Pectra upgrade in May 2025. It's a smaller mechanism that achieves much of what 4337 does with less infrastructure.

ERC-4337: smart accounts without changing the protocol

The constraint that smart contracts can't initiate transactions is at the EVM level. Changing it would mean a hard fork. ERC-4337 sidesteps the problem by building infrastructure on top that lets users sign "intent" off-chain and have someone else turn it into a real transaction.

The user signs a struct called a UserOperation that describes what they want done: which contract to call, with what data, paid for somehow. They send it to a service called a bundler instead of submitting it to the regular mempool. The bundler is just an EOA running a node. It collects UserOperations, batches them into a single real transaction, and submits that transaction to the chain. The bundler pays gas for the submission.

The bundler's transaction calls into a singleton contract called the EntryPoint. The EntryPoint is what makes the whole thing safe. For each UserOperation in the batch, the EntryPoint runs a fixed protocol:

  1. Ask the user's smart account "is this UserOperation valid?" The smart account checks the signature however it wants (ECDSA, passkey, multisig, ZK proof, whatever) and either accepts or rejects.
  2. Have the smart account execute whatever the UserOperation asked for.
  3. Make sure someone pays the bundler back for gas, plus a small profit tip.

Step 3 is where paymasters come in. If the user has ETH, they can pay the bundler directly out of their smart account's balance. If they don't, they can point to a paymaster, which is a separate contract that agrees to cover the gas. Paymasters might require payment in USDC, might check that the call is to an allowlisted dApp, might sponsor the user as part of a subscription. The protocol stays neutral about why the paymaster is willing to pay.

From the user's point of view: they sign one message in their wallet, the dApp sends it to a bundler, and a few seconds later it's on chain. They didn't hold ETH. They didn't sign a transaction. The smart account did the work using whatever signing scheme it's configured for.

The cost of this design is operational complexity. ERC-4337 deliberately avoided protocol changes, which meant inventing a parallel mempool, a parallel transaction format, and an ecosystem of bundlers and paymasters. None of that is part of Ethereum's core protocol. It all lives in contracts and off-chain services. EIP-7702 takes the opposite approach.

EIP-7702: smart accounts at the protocol level

EIP-7702 takes a different approach. Instead of building infrastructure around EOAs, it lets an EOA temporarily (or persistently) act as a smart account directly, at its own address.

The idea: introduce a new transaction type (type 0x04, the SetCode transaction) that includes an authorization list. Each authorization is signed by an EOA's private key and says "set my account's code to point to this contract."

EIP-7702: an EOA can borrow contract code, signed by its own private key Before EIP-7702: an EOA is just a keypair EOA address 0xAlice... code: (empty) balance: 2.5 ETH When anyone calls 0xAlice..., nothing executes. It's a wallet, not a contract. Step 1 — Alice signs an authorization with her private key: Authorization tuple: chainId: 1 address: 0xSmartWalletImpl... ← contract whose code to use nonce: 7 Step 2 — Anyone submits a type-0x04 transaction with that authorization: type-0x04 transaction - authorization_list: [ Alice's signed authorization ] - other normal fields (to, data, gas, ...) the submitter can be Alice OR anyone else; the auth was signed by Alice After: Alice's EOA now executes contract code when called EOA address 0xAlice... code: 0xef0100 || 0xSmartWalletImpl... ← delegation indicator balance: 2.5 ETH Calls to 0xAlice... now execute 0xSmartWalletImpl's code with Alice's storage. Persists until Alice signs another auth (could be to 0x0 to revoke). Her private key still works for normal signing alongside the delegation.

After a SetCode transaction is processed, the EOA's account state gets a delegation indicator: a small piece of data starting with 0xef0100 followed by the address of the implementation contract. The EVM treats this as the EOA's "code." When anyone calls the EOA's address, the EVM looks up the indicator, finds the implementation contract, and executes its code in the context of the EOA's storage.

Three things to notice about this design.

The authorization is signed by the EOA's private key. Nobody else can delegate your account's code to a contract. The protocol checks this signature before applying the delegation, exactly like it checks a transaction signature.

The delegation persists across transactions. Once Alice has delegated her account to a smart wallet implementation, that delegation stays in place until she signs another authorization (which could be to a different contract, or to the zero address to revoke). She doesn't need to re-sign every time.

The EOA doesn't lose its key-based functionality. Alice's private key still works for signing regular transactions. The delegation just adds the ability to also be called as a contract. The two paths coexist.

This is the smaller, simpler version of account abstraction. No alternative mempool, no bundlers, no EntryPoint. The user signs one authorization, points it at a smart wallet implementation, and from that point on their EOA behaves like a smart account. They can still send normal transactions with ECDSA signatures. Anyone can also call into their address and execute the smart-wallet logic.

What this combination enables

The features the AA community has been building toward become real once smart accounts can self-initiate. None of them are new ideas. The blockers were always at the account layer.

Passkeys instead of private keys. A smart account can implement validateUserOp to accept WebAuthn signatures. Now users authenticate transactions with their device's biometric, with no seed phrase to lose. The actual key never leaves the secure enclave on their phone.

Social recovery. If a user loses access to their primary signer, designated guardians (other addresses they trust) can collectively replace the signer after a delay. The account doesn't get wiped out by a lost key.

Sponsored gas. A dApp covers gas for first-time users via a paymaster (4337) or a relayer sending a type-0x04 transaction on the user's behalf (7702). Onboarding goes from "first buy ETH from an exchange, then use our app" to "use our app, we'll pay your gas."

Gas in any token. A user pays gas in USDC. The paymaster (or wrapper logic in the smart account) accepts the USDC, converts it or charges it directly, and pays the actual ETH gas to the bundler or block builder.

Batched operations. Approve USDC, swap for ETH, and stake the ETH, all in a single user-signed operation. No three pop-ups, no three transactions, no waiting for confirmations between them.

Session keys. A user authorizes a temporary, restricted key for a specific dApp: "this key can spend up to 100 USDC, only on the game contract, for the next 4 hours." The dApp can submit operations on the user's behalf within those bounds without re-prompting. When the session expires, the key is dead. This is what makes blockchain games and high-frequency apps feel native rather than transactional.

Atomic conditional execution. A smart account can require that a swap return at least a certain output, or that two operations both succeed or neither does. The account itself enforces the policy, so this works across protocols that don't natively support it.

ERC-4337 vs EIP-7702: when each fits

4337 and 7702 are not mutually exclusive. A modern smart-wallet design might use both: 7702 to bring existing EOAs under contract control, then 4337 for the rich infrastructure of bundlers and paymasters when sponsored gas or alt-mempool batching matters.

4337 alone makes sense when users are starting fresh and willing to use a new address that's a contract from day one. Some wallet providers default to this for new users.

7702 alone is the right fit for existing users with EOAs that already have an on-chain history. They don't have to move funds to a new address. They just sign one authorization and their existing account gets smart-wallet logic.

Both together is becoming the production pattern for serious smart-wallet projects. Users start with 7702-delegated EOAs for upgrade-in-place. Their delegated implementation supports the 4337 interface, so the same wallet integrates with bundler infrastructure and paymasters for gas sponsorship.

A nice side-effect of 7702: every existing EOA can become a smart account at any time. There's no migration friction. Users who never knew or cared about smart accounts can be upgraded transparently by a wallet provider, with their consent.

A few things to keep in mind

The smart-account contract is itself an attack surface. A bug in the implementation contract is a bug in every account delegated to it. Same for the EntryPoint. Both have been audited heavily but the principle stays: the security of your account depends on the security of the code controlling it.

Bundler censorship is a real concern. If only a few bundlers exist and they all refuse to include UserOps from certain users (sanctioned addresses, for example), those users are de-facto blocked from using 4337. The mitigation is many independent bundlers, and the protocol's open structure aims to keep entry low.

EIP-7702 has subtle gotchas around storage compatibility. If two different implementation contracts use the same storage slots for different things, switching delegation between them can leave your account's state in a meaningless configuration. The fix is to use stable storage layouts (often via ERC-7201 namespaced storage) so swapping implementations doesn't conflict.

Signature verification still costs gas. A smart account that does ECDSA on every UserOp pays roughly the same as an EOA would. Fancier schemes (multisig, ZK proofs) cost more. The bill shows up in the verification gas limit on each UserOp.