Skip to content

Overview

EIP-7702 gives superpowers to EOAs.

Specifically, it allows any EOA to set its code based on any existing smart contract. To do so, an EOA owner would sign an authorization that could then be submitted by anyone as part of the new transaction type. The code will be valid until replaced by another authorization. The authorization could be given for a single chain, or all chains at once.

This setup allows an EOA to mimic a smart contract account, particularly allowing transaction bundling, gas sponsorships, and custom permissioning schemes.

Motivation

Flexible

EIP-7702 offers some guardrails yet it is very flexible. Users can provide both single-chain and cross-chain authorizations, as well as choose what proxy to use. While most wallets would probably not allow the most flexible behavior, it still opens up a way for different vendors to experiment and innovate.

Compatible with EIP-4337

It is easy to use EIP-7702 with EIP-4337, so most of the infrastructure (e.g. paymasters, bundlers, RPC endpoints) would just work.

Compatible with existing smart accounts

As EIP-7702 allows an EOA to set its code directly and supports writing to storage, it should be possible with little to no effort to use existing smart account implementations.

Specification

The EIP introduces a new transaction, “set code transaction”, where the TransactionType is 0x04 and the TransactionPayload is the RLP serialization of the following:

rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, value, data, access_list, authorization_list, signature_y_parity, signature_r, signature_s])
 
authorization_list = [[chain_id, address, nonce, y_parity, r, s], ...]

The authorization_list is a list of tuples that store the address to code which the signer desires to execute in the context of their EOA.

The ReceiptPayload for this transaction is rlp([status, cumulative_transaction_gas_used, logs_bloom, logs]).

Behavior

At the start of executing the transaction, for each [chain_id, address, nonce, y_parity, r, s] tuple:

  1. Verify the chain id is either 0 or the chain’s current ID.
  2. Verify the nonce is less than 2**64 - 1.
  3. authority = ecrecover(keccak(0x05 || rlp([chain_id, address, nonce])), y_parity, r, s]
  • s value must be less or equal than secp256k1n/2, as specified in EIP-2.
  1. Add authority to accessed_addresses (as defined in EIP-2929.)
  2. Verify the code of authority is either empty or already delegated.
  3. Verify the nonce of authority is equal to nonce. In case authority does not exist in the trie, verify that nonce is equal to 0.
  4. Add PER_EMPTY_ACCOUNT_COST - PER_AUTH_BASE_COST gas to the global refund counter if authority exists in the trie.
  5. Set the code of authority to be 0xef0100 || address. This is a delegation designation.
  • As a special case, if address is 0x0000000000000000000000000000000000000000 do not write the designation. Clear the accounts code and reset the account’s code hash to the empty hash 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470.
  1. Increase the nonce of authority by one.

If any of the above steps fail, immediately stop processing that tuple and continue to the next tuple in the list. It will in the case of multiple tuples for the same authority, set the code using the address in the last valid occurrence.

Note that the signer of an authorization tuple may be different than tx.origin of the transaction.

If transaction execution results in failure (any exceptional condition or code reverting), setting delegation designations is not rolled back.