Delegate an Ethereum EOA under EIP-7702 and a USDC signature that was valid yesterday can revert today with FiatTokenV2: invalid signature. The key, the digest and the token contract have not changed. The ranking guides I read on EIP-7702 vs ERC-4337 never reach this, because they compare wallet architectures and stop before the token contract.
This guide compares them for teams moving stablecoins, where a wrong answer shows up as a payment that fails at settlement.
EIP-7702 vs ERC-4337: What Is the Difference?
EIP-7702 is a protocol change. A new transaction type lets an EOA point its code at a contract and keep its address. ERC-4337 needed no protocol change: it is a shared EntryPoint contract plus an off-chain mempool, where bundlers submit UserOperations and paymasters cover the gas.
The usual line is that the two are complementary, and that is correct. EIP-7702 gives an existing address some code. ERC-4337 supplies the sponsorship market. The difference that matters for money is who holds final authority.
| EIP-7702 | ERC-4337 | |
|---|---|---|
| Layer | Protocol, transaction type 0x04 | Contracts plus bundlers |
| Status | Final, on Ethereum since 7 May 2025 | Final |
| Address | Keeps the EOA address | New contract address, unless combined with 7702 |
| Final authority | The original private key, always | Whatever the account's validation logic says |
| Key rotation | Not possible | Possible |
| Gas sponsorship | Any relayer that will send the transaction | Paymasters, through the EntryPoint |
| Setup cost | 25,000 gas per authorisation, 12,500 refunded on existing accounts | Account deployment through initCode |
| Concurrent sends | One in-flight transaction from the EOA in geth | Parallel nonce channels (192-bit key, 64-bit sequence) |
Beyond Ethereum, BNB Chain activated EIP-7702 with Pascal on 20 March 2025, and OP Mainnet and Base followed with Isthmus on 9 May 2025. Arbitrum scheduled ArbOS 40 for 17 June 2025, and Polygon's Bhilai fork landed on 1 July 2025.
How Does an EIP-7702 Authorisation Work?
Each entry in the authorization_list is a signed tuple:
{
"chain_id": 8453,
"address": "0xDelegateImplementation",
"nonce": 17,
"y_parity": 1,
"r": "0x...",
"s": "0x..."
}
The signed digest is keccak(0x05 || rlp([chain_id, address, nonce])). Once processed, the account's code becomes 0xef0100 || address, which is 23 bytes. Four details cause most of the production bugs.
chain_id: 0is valid on every chain. One signature installs the delegate anywhere the nonce matches. Never request one from a customer.- Self-sending shifts the nonce. The sender's nonce is incremented before the list is processed, so an EOA paying for its own delegation signs the transaction nonce plus one. viem handles this when you pass
executor: 'self'tosignAuthorization. - Invalid tuples are skipped, not fatal. The spec says a failing tuple is abandoned and processing moves to the next one. The transaction still runs. If it was addressed to an EOA with no earlier delegation, it hits empty code and returns status 1. No delegate executed, no USDC moved, and the receipt says success.
- Clearing leaves storage behind. Delegating to the zero address resets the code hash, but the account's storage stays where it was.
ERC-4337 EntryPoint Versions and UserOperation Fields in 2026
Paymasters and bundlers support specific EntryPoint versions, so the version is an integration constraint and not a detail.
| Version | Address | Note |
|---|---|---|
| v0.6 | 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 | Unpacked UserOperation |
| v0.7 | 0x0000000071727De22E5E9d8BAf0edAc6f37da032 | PackedUserOperation |
| v0.8 | 0x4337084d9e255ff0702461cf8895ce9e3b5ff108 | March 2025, native 7702 support |
| v0.9 | 0x433709009B8330FDa32311DF1C2AFA402eD8D009 | November 2025 |
A PackedUserOperation carries sender, nonce, initCode, callData, accountGasLimits, preVerificationGas, gasFees, paymasterAndData and signature.
From v0.8, eth_sendUserOperation accepts an eip7702Auth field, and an initCode beginning 0x7702 (right-padded to 20 bytes) marks the sender as a delegated EOA. The 25,000 authorisation cost has to be included in preVerificationGas, which is the easy one to miss when you port an estimator.
Validation is restricted by ERC-7562. ORIGIN, TIMESTAMP and BLOCKHASH are banned during validation, a UserOperation may carry one authorisation, and a delegated account can only appear as the sender. The timestamp ban is why Circle Paymaster's permit uses a maxUint256 deadline, as I covered in the EIP-3009 vs EIP-2612 vs Permit2 guide.
EIP-7702 vs ERC-4337 Gas Costs: What the Benchmarks Show
I could not find a measured, like-for-like ERC-20 transfer across all three paths. The most useful public numbers measure an empty execute, so read them as overhead rather than as the cost of a payment.
| Path | Gas | Source |
|---|---|---|
Direct execute | 31,679 | Openfort 7702 benchmark |
| ERC-4337, self-paid | 92,995 | Openfort |
| ERC-4337, sponsored | 104,083 | Openfort |
| ERC-4337, gas paid in ERC-20 | 132,755 | Openfort |
Direct execute | 31,121 | eth-infinitism gas checker |
| ERC-4337, single-op bundle | 77,742 | eth-infinitism |
| ERC-4337, marginal op in a bundle | 41,882 | eth-infinitism |
A lone UserOperation carried about 61,000 gas of overhead in Openfort's test, and paying gas in an ERC-20 added nearly 40,000 more, because the paymaster has to move the token. Inside a busy bundle the marginal overhead falls to around 10,800. ERC-4337 overhead is mostly a shared fixed cost, so it rewards volume. On a quiet chain or a low-traffic bundler you pay all of it.
A relayer sending a type-4 transaction skips the EntryPoint entirely, and the 12,500 to 25,000 delegation charge is paid once per delegation. On a rollup, the L1 data component can matter more than execution gas, and a UserOperation carries more calldata than a direct call. Benchmark your own transfer path in Foundry before you quote a number to finance.
Why a Delegated EOA Can Fail USDC transferWithAuthorization
USDC's SignatureChecker picks its verification path from the payer's code. This is my paraphrase of the logic:
if extcodesize(signer) == 0:
valid = ecrecover(digest, signature) == signer
else:
valid = signer.isValidSignature(digest, signature) == 0x1626ba7e
There is no ECDSA fallback, and EXTCODESIZE returns 23 for a delegated EOA. The v, r, s overloads pack into bytes and take the same route.
I tested this with read-only eth_call simulations against USDC on Ethereum and Base: a throwaway key, a zero-value transferWithAuthorization, one raw ECDSA signature, and the payer's code set to 0xef0100 || delegate by state override. No transactions were sent.
| Payer state | Result |
|---|---|
| Plain EOA | Success |
| Delegated to a contract with no ERC-1271 (Multicall3) | FiatTokenV2: invalid signature |
Delegated to MetaMask EIP7702StatelessDeleGator | Success |
Delegated to Simple7702Account | Success |
Delegated to Base EIP7702Proxy | Success |
Having isValidSignature is necessary but not sufficient. Biconomy Nexus routes on a validator address in the first 20 bytes of the signature and rejected the raw signature, though my test account was uninitialised, so treat that as a weak result. Coinbase's smart wallet verifies against a replaySafeHash wrapper, and its EIP7702Proxy adds a fallback to the EOA's own key.
The same branch now exists across the verifiers you are likely to touch:
| Verifier | When the signer has code |
|---|---|
USDC SignatureChecker | ERC-1271 only |
Permit2 SignatureVerification | ERC-1271 only |
OpenZeppelin SignatureChecker v5.1.0+ | ERC-1271 only |
OpenZeppelin SignatureChecker up to v5.0.2 | ECDSA first, then ERC-1271 |
So your own contract can give a different answer depending on the OpenZeppelin version it was compiled against.
The check runs at settlement, not at signing. A customer who signs an authorisation and then delegates before your relayer submits it can see the payment fail, and re-delegating or clearing can flip outstanding authorisations in either direction. An open x402 pull request documents the behaviour. I could not find any statement on it from Circle.
What EIP-7702 Breaks in Payment Contracts and Hot Wallets
msg.sender == tx.originno longer proves the caller has no code. The spec names sandwich protection and reentrancy guards as casualties. OpenZeppelin's write-up of a 24 August 2025 BSC exploit describes a delegated EOA passing that check on a staking contract, for about $85,000.isContractguards now return true for delegated EOAs. If your payout path treats code-bearing addresses differently, one customer address can change category between two withdrawals. USDC has no receiver hook, so plain payouts to delegated EOAs still work.- Nonce queues. The spec tells clients to hold only one pending transaction for a delegated EOA, and geth enforces it with
ErrInflightTxLimitReached. A hot wallet that stacks nonces will start getting rejections once its sending address is delegated. - Policy limits. The private key keeps full control, so spend limits in a delegate bind only callers who go through the delegate. If that key sits with an AI agent, the enforcement belongs in the signer, as in the Privy vs Turnkey vs CDP comparison.
- Initialisation and storage. There is no
initcode, so setup calldata must be signed by the EOA or anyone can front-run it. Re-delegating inherits old storage, which is why the spec points to ERC-7201 namespacing.
Paymaster Fees in 2026: Circle vs Pimlico vs Alchemy vs Coinbase
| Provider | Published fee | Scope |
|---|---|---|
| Circle Paymaster | 10% gas surcharge | USDC only. v0.7 on Arbitrum and Base; v0.8 on Arbitrum, Avalanche, Base, Ethereum, Optimism, Polygon, Unichain |
| Pimlico | 10% on sponsored gas, plus roughly a cent per UserOperation | Multi-chain |
| Alchemy | 8% admin fee on pay-as-you-go | Multi-chain |
| Coinbase CDP | 7% | Base only |
These are November 2026 list prices. On a chain where a UserOperation costs a fraction of a cent, any fixed per-operation charge outweighs the percentage, so model both components at your real gas price.
Circle's v0.8 quickstart uses toSimple7702SmartAccount, which passed the USDC signature test above. Running your own relayer removes the percentage but adds key management, nonce management and a new risk: the spec warns that an account can invalidate its authorisation or sweep its funds and leave the relayer unpaid.
Is EIP-7702 Safe? Sweepers and Phishing Numbers
A USENIX Security 2026 paper counted 2,322,548 malicious authorisations out of 3,664,166 across seven chains up to 15 July 2025, or about 63%. Press coverage of Wintermute's June 2025 data ranged from over 80% to over 97%, and I trust the paper's denominator more.
The sweepers Wintermute tracked were draining keys that had already leaked, and they were reported as largely unprofitable. The live threat is phishing. Two batch-signature cases in August 2025 took roughly $1 million and $1.54 million, because one signature can now approve a whole bundle of calls.
Should Payment Teams Use EIP-7702 or ERC-4337?
This is my position, for payment flows specifically.
- USDC to a known payee with sponsored gas: neither. EIP-3009 through a relayer needs no account change, no EntryPoint and no delegate to audit.
- Existing EOAs holding balances: EIP-7702 with EntryPoint v0.8 or later. The address stays and paymasters still work. Choose a delegate that accepts a raw ECDSA digest through
isValidSignature. - Treasury, multi-party approval, or agents with hard limits: a pure ERC-4337 or multisig contract account. A limit the original key can bypass is only a suggestion.
What This Means for Payment Engineers
1. Add a delegated payer to your test matrix. A state override setting 0xef0100 || delegate reproduces it without a transaction.
2. Read eth_getCode at settlement. A 23-byte result starting 0xef0100 tells you the delegate. Compare it to an allowlist and re-check immediately before you submit.
3. Confirm payment from Transfer logs, never from receipt status alone. A skipped tuple returns status 1.
4. Keep hot-wallet senders undelegated. Let delegated accounts go through a bundler, which is the transaction sender, so the one-pending limit does not apply to them.
5. Pin your SignatureChecker version and re-test when you cross OpenZeppelin v5.1.
6. Remove tx.origin and isContract as security checks. Both were weak before and are wrong now.
7. Integrate through ERC-5792 and ERC-7677. wallet_getCapabilities and pm_getPaymasterData keep you off vendor-specific SDK paths when you change paymaster.
I'm Tom Wang. If you take one test from this, simulate a USDC authorisation from a delegated payer before a customer's wallet does it for you. It takes an afternoon and covers the failure none of the comparison tables mention.