-
-
Published
Linked with GitHub
# Can EIP-3074 and ERC-4337 be used together?
EIP-3074 and ERC-4337 [do not solve the same problem](https://notes.ethereum.org/@yoav/erc-4337-vs-eip-3074-false-dichotomy). Can they be combined?
The answer is yes. It is possible to give EOA some of the ERC-4337 benefits by combining ERC-4337 and EIP-3074, and almost all of the benefits if combining them with EIP-5003.
### An EIP-3074 invoker as the ERC-4337 account logic of an EOA
It's possible to build an invoker that serves as the ERC-4337 account logic for EOAs. Here's how:
ERC-4337 allows multi-tenant accounts that can process multiple unordered transactions in parallel, if the account is staked. If the account's `validateUserOp()` function behaves non-deterministically and causes unexpected invalidations, the account gets throttled in mempool.
An invoker could become such an account by implementing a `validateUserOp()` that verifies the AUTH signature. This function is deterministic so the account won't get throttled. To allow parallel execution by multiple users, it will use the EOA's address as the `key` part of the 4337 nonce, so each EOA has its own nonces sequence that doesn't conflict with others
EOA users will send UserOps where `UserOp.sender=address(4337Invoker)` and `UserOp.signature` contains the AUTH signature for the UserOp. The invoker will get called by `EntryPoint`, validate the signature and accept the UserOp. `UserOp.paymaster` may specify a paymaster to be used by this EOA operation. For example, the EOA could use a TokenPaymaster to pay the gas with ERC-20 tokens it holds. After gas payment, `EntryPoint` will execute the invoker, which will perform the AUTH+AUTHCALL on behalf of the EOA.
This invoker solves the relaying problem, enabling gas abstraction for the EOA. However, it doesn't solve authentication and authorization because the EOA still has an ECDSA key that could be used "outside the system" to bypass any other signature scheme or access control restrictions.
### An ultra-cheap way to create an ERC-4337 account
The method above could be used as a cheap form of account abstraction, if the user destroys the EOA key immediately after signing an AUTH commit for 4337Invoker, or using a variation of [Nick's method](https://yamenmerhi.medium.com/nicks-method-ethereum-keyless-execution-168a6659479c) to generate the AUTH signature.
If there is no live key, then the invoker becomes the only implementation of the account - effectively making the EOA an ERC-4337 account without paying for contract deployment.
Every UserOp of such account will set `UserOp.sender=4337Invoker`, and put the fixed AUTH signature in `UserOp.signature` along with whatever signature this invoker uses as an ERC-4337 account. In `validateUserOp` the invoker will recover the account address from the AUTH signature, validate the real signature, and then in execution it'll use AUTH+AUTHCALL to execute `UserOp.calldata` on behalf of the account.
This invoker could even be extended to allow the user to change account implementation in the future, by acting as a multiplexer and holding an `implementations[account]` mapping that can be modified by the account itself through an AUTHCALL after it passes validation with the current implementation. The implementations will just have to keep any account-specific storage (such as keys) in an `accountData[account]` mapping in order to access it during validation without violating the ERC-4337 mempool rules.
If [EIP-7557](https://ethereum-magicians.org/t/eip-7557-block-level-warming/16642) is accepted in the future, then this method also becomes cheaper to transact with, not just to deploy. It is likely that a lot of EOAs will use the same 4337Invoker, so the cost of warming it and loading its code (post-verkle) will be amortized across a large number of transactions.
One downside of this method, is that the user won't be able to use the same address across different chains. There is no ECDSA key, and no CREATE2 factory involved. But for many users it may be a good trade-off - get the benefits of account abstraction without paying for deployment, in exchange for not being able to have the same address on other networks.
### Full in-place migration to ERC-4337 using EIP-5003.
The invoker above could use EIP-5003 to revoke (AUTHUSURP) the EOA's ECDSA key and replace it with any ERC-4337 account implementation. This combination enables the use of gas abstraction during the migration itself.
Example:
Suppose the user starts with an EOA that has USDC but no ETH, and wishes to get the benefit of full account abstraction. The flow would look like this:
1. The user sends a UserOp where `UserOp.sender = UserOp.paymaster = 4337MigrationInvokerWithUsdcSupport`, `UserOp.calldata=migrateMe(implementation)` and `UserOp.signature` is an AUTH commitment to `4337MigrationInvokerWithUsdcSupport`.
2. `EntryPoint` calls `4337MigrationInvokerWithUsdcSupport.validateUserOp`, which just verifies that `UserOp.paymaster==address(this)`, since the rest will be done as a paymaster.
3. `EntryPoint` calls `4337MigrationInvokerWithUsdcSupport.validatePaymasterUserOp` which uses AUTH with the signature from `UserOp.signature` then AUTHCALL to make the EOA call `USDC.transfer()` in order to precharge it.
4. `EntryPoint` calls `4337MigrationInvokerWithUsdcSupport(implementation)` which uses AUTH+AUTHUSURP to migrate the EOA to the new implementation.
5. `EntryPoint` calls `4337MigrationInvokerWithUsdcSupport.postOp` which calculates the USDC cost of the gas used, and refunds the remaining USDC to the newly migrated account.
This flow uses EIP-3074 and EIP-5003 to migrate an EOA to full ERC-4337 account abstraction without using anything other than UserOps, so it can use any ERC-4337 features such as gas abstraction during the migration.
**Caveat: [EOA migration considered harmful](https://notes.ethereum.org/@yoav/erc-4337-vs-eip-3074-false-dichotomy#Caveat:-EOA-migration-considered-harmful)**