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. authority = ecrecover(keccak(0x05 || rlp([chain_id, address, nonce])), y_parity, r, s]
  2. Verify the chain id is either 0 or the chain’s current ID.
  3. Verify that the code of authority is either empty or already delegated.
  4. Verify the nonce of authority is equal to nonce.
  5. Refund the sender PER_EMPTY_ACCOUNT_COST - PER_AUTH_BASE_COST gas if authority exists in the trie.
  6. Set the code of authority to be 0xef0100 || address. This is a delegation designation.
  7. Increase the nonce of authority by one.
  8. Add the authority account to accessed_addresses

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 occurrence.

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