Alert Source Discuss
⚠️ Draft Standards Track: Core

EIP-7702: Set EOA account code for one transaction

Add a new tx type that sets the code for an EOA during one transaction execution

Authors Vitalik Buterin (@vbuterin), Sam Wilson (@SamWilsn), Ansgar Dietrichs (@adietrichs), Matt Garnett (@lightclient)
Created 2024-05-07
Discussion Link https://ethereum-magicians.org/t/eip-set-eoa-account-code-for-one-transaction/19923
Requires EIP-2718, EIP-2929, EIP-2930

Abstract

Add a new transaction type that adds a contract_code field and a signature, and converts the signing account (not necessarily the same as the tx.origin) into a smart contract wallet for the duration of that transaction. Intended to offer similar functionality to EIP-3074.

Motivation

There is a lot of interest in adding short-term functionality improvements to EOAs, increasing the usability of applications and in some cases allowing improved security. Three particular applications include:

  • Batching: allowing multiple operations from the same user in one atomic transaction. One common example is an ERC-20 approval followed by spending that approval, a common workflow in DEXes that requires two transactions today. Advanced use cases of batching occasionally involve dependencies: the output of the first operation is part of the input to the second operation.
  • Sponsorship: account X pays for a transaction on behalf of account Y. Account X could be paid in some other ERC-20 for this service, or it could be an application operator including the transactions of its users for free.
  • Privilege de-escalation: users can sign sub-keys, and give them specific permissions that are much weaker than global access to the account. For example, you could imagine a permission to spend ERC-20 tokens but not ETH, or to spend up to 1% of total balance per day, or to interact only with a specific application.

EIP-3074 solves all of these use cases. However, it has forward-compatibility concerns:

  • It introduces two opcodes, AUTH and AUTHCALL, that would have no use in an “endgame account abstraction” world where eventually all users are using smart contract wallets (which seems like it must happen eventually, at the least because eventually quantum computers will break the ECDSA that EOAs use)
  • It leads to the development of an “invoker contract” ecosystem that would be separate from the “smart contract wallet” ecosystem, leading to possible fragmentation of effort.

The purpose of this EIP is to enable all of the use cases of EIP-3074, without these two weaknesses.

Specification

The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

Parameters

  • FORK_BLKNUM = TBD
  • TX_TYPE = TBD
  • MAGIC = TBD
  • PER_CONTRACT_CODE_BASE_COST = 5000

As of FORK_BLOCK_NUMBER, a new EIP-2718 transaction is introduced with TransactionType = TX_TYPE(TBD).

The EIP-2718 TransactionPayload for this transaction is

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

The intrinsic cost of the new transaction is inherited from EIP-2930, specifically 21000 + 16 * non-zero calldata bytes + 4 * zero calldata bytes + 1900 * access list storage key count + 2400 * access list address count. Additionally, we add a cost of 16 * non-zero calldata bytes + 4 * zero calldata bytes over each contract_code, plus PER_CONTRACT_CODE_BASE_COST times the length of the contract_code array.

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

  1. Let signer = ecrecover(keccak(MAGIC + contract_code), y_parity, r, s].
  2. Verify that the contract code of signer is empty.
  3. Set the contract code of signer to contract_code.
  4. Add the signer account to accessed_addresses (as defined in EIP-2929.)

At the end of the transaction, set the contract_code of each signer back to empty.

Note that the signer of any of the contract_code signatures, and the tx.origin of the transaction, are allowed to be different.

Rationale

Conversion of EIP-3074 use cases

In this design, it requires fairly little work to convert an existing EIP-3074 workflow. Specifically, AUTH and AUTHCALL would get replaced by calls into the EOA. One way to do this is that the contract_code would be a user wallet (which could be a DELEGATECALL forwarder to save gas), and would expose two functions, verify and execute.

  • AUTH would be replaced by a code to verify, which would use TSTORE to locally set authorized[msg.sender, ...] = True.
  • AUTHCALL would be replaced by a call to execute, which would use TLOAD to verify authorized[msg.sender, ...], and then execute from there.

Hence, there is a very simple transformation from “existing EIP-3074 workflows” into workflows under this new scheme.

Forward-compatibility with future account abstraction

This EIP is designed to be very forward-compatible with endgame account abstraction, without over-enshrining any fine-grained details of ERC-4337 or RIP-7560.

Specifically:

  • The contract code that users would need to sign could literally be existing ERC-4337 wallet code.
  • The “code pathways” that are used are code pathways that would, in many cases (though perhaps not all), continue to “make sense” in a pure-smart-contract-wallet world.
  • Hence, it avoids the problem of “creating two separate code ecosystems”, because to a large extent they would be the same ecosystem. There would be some workflows that require kludges under this solution that would be better done in some different “more native” under “endgame AA”, but this is relatively a small subset.
  • It does not require adding any opcodes, that would become dangling and useless in a post-EOA world.
  • It allows EOAs to temporarily convert themselves into contracts to be included in ERC-4337 bundles, in a way that’s compatible with the existing EntryPoint.
  • Once this is implemented, EIP-5003 is “only one line of code”: just add a flag to not set the code back to empty at the end.

Backwards Compatibility

This EIP breaks the invariant that an account balance can only decrease as a result of transactions originating from that account. This has consequences for mempool design, and for other EIPs such as inclusion lists. However, these issues are common to any proposal that provides similar functionality, including EIP-3074.

Security Considerations

Many security considerations with EIP-3074 are shared. Particularly, user wallets need to be very careful about which contract_code they sign.

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Vitalik Buterin (@vbuterin), Sam Wilson (@SamWilsn), Ansgar Dietrichs (@adietrichs), Matt Garnett (@lightclient), "EIP-7702: Set EOA account code for one transaction [DRAFT]," Ethereum Improvement Proposals, no. 7702, May 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7702.