How EIP7702 works with ERC4337?

ERC4337 and EIP7702

Okay guys, I assume that you already know how ERC4337 works. I think contract wallet is a second-class citizen in EVM eco-system since it was born, because its gas cost, over payed gas to bundlers, and it's cumbersome to use and maintain (cross-chain data sync, cross-chain address).

So, even though I know a lot about ERC4337, I haven't used it much.

Now we have a new revolution: EIP7702, it makes it easy for EOA to have smart contract capabilities, like Batch Execution, Gas Sponsorship, and more capabilities like smart contracts.

Basiclly EIP7702 add a new transaction type 0x4, added a new field like maxPriorityFeePerGas called authorization_list, they are on the same level, its role is to allow an EOA be delegated to a contract address.

Anyone can call it as a proxy contract until you cancel it.

// DON'T USE IN PRODUCTION
contract BatchExecutor {
   function batch(address[] calldata to, bytes[] calldata call, uint256[] calldata val) external {
      for ... {
         to.call{value: val}(call)
      }
   }
}

For example, an EOA (0xeaea) want's to use the BatchExecutor contract (0xbebe)'s code to do a swap operation. Generally speaking, perform a swap operation requires 2 steps: eaea:approve -> eaea:swap, however with the EIP7702, the EOA can also do this in 1 step delegate:bebe:batch(approve->swap).

Steps for using EIP7702

As defined in EIP7702, the you(EOA) wishing to operate as the Batch Executor smart contract is required to sign an authorization commit.

Setup a delegation

authorization_list = [ your private key -> sign (hash(chainid, deployed contract address, nonce)) ]

authorization_list is an array of signatures to validate your address and the contract you wants to use.

Anyone can send a transaction use this signaure (tx.origin != signer is allowed), it simply serves to place the contract code on the signer's address during transaction execution.

So you(EOA) or anyone else can send a transaction call EOA address.batch([tokenAddress, routerAddress], [approve, swap], [0, 0]) to use your address and your assets. Because any contracts and transaction sender may call the contract in your address, so you need to check the permission validation in the contract you are using (like require(msg.sender == address(this)) check the caller is yourself).

Your EOA will proxy to the authorized contract until you cancel the delegation.

Cancel the delegation

authorization_list = [ your private key -> sign (hash(chainid, 0x0000000000000000000000000000000000000000, nonce)) ]

Send a transaction again with this authorization_list, you will cancel the delegation, and you can't call it as a contract anymore.

Work together

Based on EIP7702, only need your(EOA) signature for authorization tuple and anyone can use that signature in authorization_list, making EIP7702 very easy to use with ERC4337.

It's a one-time process that will works forever:

  1. user(EOA) sign the authorization tuple get a signature (bind a erc 4337 wallet contract)
  2. user build and sign a UserOperation (call your EOA address as a 4337 wallet)
  3. user send the authorization commit (address, chain id, nonce, signature) and the UserOperation to bundler
  4. bundler build a EIP7702 transaction(type 0x4) to call the EntryPoint
  5. repeat from 2

Please correct any errors and thanks for reading.

Comments