EIP-7701: Native Account Abstraction

Native Account Abstraction protocol, relying on a new transaction type and a family of opcodes


Metadata
Status: DraftStandards Track: CoreCreated: 2024-05-01
Authors
Vitalik Buterin (@vbuterin), Yoav Weiss (@yoavw), Alex Forshtat (@forshtat), Dror Tirosh (@drortirosh), Shahaf Nacson (@shahafn)

Abstract


We propose splitting the Ethereum transaction scope into multiple steps: validations, execution, and post-operation logic. Transaction validity is determined by the result of the validation steps of a transaction.

We further separate transaction validation for the purposes of authorization and the gas fee payment, allowing one contract to pay gas for a transaction that will be executed from another contract.

Motivation


Native Account Abstraction allows custom validation logic of a transaction and custom gas payment logic, opening new use-cases and features for wallets and dApps.

Specification


Constants

NameValue
AA_TX_TYPETBD
AA_ENTRY_POINTaddress(0x7701)
AA_BASE_GAS_COST15000

New Transaction Type

A new EIP-2718 transaction with type AA_TX_TYPE is introduced. Transactions of this type are referred to as "AA transactions".

Their payload should be interpreted as:


Definitions

  • Smart Contract Account: an Ethereum smart contract that serves as the user's account and on-chain identity. It is responsible for holding user's assets, verifying user requests, and executing actions on the user's behalf.
  • Sender: the Smart Contract Account sending the current AA transaction.
  • Paymaster: a smart contract that is requested to pay gas fees for the current AA transaction on behalf of the Sender contract.
  • Factory: a smart contract that performs a deployment for a new Sender contract if necessary in the context of the current AA transaction.
  • Entity: a common term for any of the smart contracts mentioned above in the context of an EIP-7701 Transaction.
  • Transaction Validity: A property of an Ethereum transaction that describes whether this transaction can be included in a block without a violation of the ethereum execution and consensus rules. This property depends on both the inputs of the transaction and the current state of the Ethereum blockchain and can change over time.
  • EIP-7701 Transaction: the entire transaction initiated by the Sender Smart Contract Account and represented with an EIP-2718 compatible Transaction Envelope object.
  • Call Frame: The context and state for a specific function call during contract execution, including input parameters, local variables, and the execution environment.
  • Top-Level Call Frame: The initial execution context of a transaction accessing the contract, the "entry point" to the EVM code.
  • EIP-7701 Call Frame: A single atomic element of EVM code execution, represented by a single top-level call to a specific address with a given data. An EIP-7701 call frame may contain inner call frames as well, but they are not referred to as "EIP-7701 call frames". An EIP-7701 call frame may either succeed or revert.
  • Frame's Role: An identifier of an action that the invoked contract is asked to make during the current call frame. An Entity may have one or more roles as part of the EIP-7701 Transaction flow.
  • EIP-7701 Transaction Phase: A set of EIP-7701 Call Frames that form a single step in an EIP-7701 Transaction flow. There are two phases in an EIP-7701 Transaction: validation and execution
  • Validation phase: A set of EIP-7701 Call Frames that define the current EIP-7701 Transaction's Validity by executing the validation EVM code.
  • Execution phase: A set of EIP-7701 Call Frames that perform the actions according to the Sender and the Paymaster contracts' interpretation of the user input. These frames do not define the Validity of the transaction.

The base gas cost of this transaction is set to AA_BASE_GAS_COST instead of 21000 to reflect the lack of "intrinsic" ECDSA signature verification.

Validation and PostOp call frame roles

We define the following values as valid ones for the current_frame_role variable:


New ACCEPTROLE opcode

This opcode allows the invoked contract to explicitly accept executing a certain role as an entity in the EIP-7701 transaction. This opcode is treated same as the INVALID (0xFE) opcode if executed in a transaction of a different type.

It takes 3 stack argument:

  • role: the exact role this entity agrees to perform.
  • offset: byte offset in the memory in bytes, to copy what will be the return data of this context.
  • size: byte size of the return data to copy.

A valid call to the ACCEPTROLE opcode is an equivalent of the RETURN (0xF3) opcode and exits the current context successfully.

Global current_frame_role variable

During the execution of the Sender, Paymaster or a Deployer code as defined by the AA_TX_TYPE transaction, the global current_frame_role variable is set to the corresponding role. The current_frame_role remains set through an uninterrupted chain of DELEGATECALL calls.

By default, the value for current_frame_role is not set. Call frames initiated with any opcodes other than DELEGATECALL run without a role.

If by the end of the execution of the Sender, Paymaster or a Deployer code current_frame_role is not explicitly accepted by using the ACCEPTROLE opcode, the EIP-7701 Call Frame reverts.

An EIP-7701 transaction is valid if and only if the following conditions are met for each of role_sender_deployment, role_sender_validation, role_paymaster_validation:

  • The top-level call frame did not revert.
  • ACCEPTROLE was called exactly once and with the correct role input parameter equal to current_frame_role, either in the top level call frame, or in an uninterrupted chain of DELEGATECALL calls.

The role_sender_execution and role_paymaster_post_op EIP-7701 Call Frame is reverted if a corresponding ACCEPTROLE opcode was not executed, executed for a wrong role, or executed more than once.

New TXPARAMLOAD, TXPARAMSIZE, and TXPARAMCOPY opcodes

Accessing transaction details within call frames is performed using the new TXPARAM* opcode family. The instructions accept the parameter identifier value that we call txparam_id.

The TXPARAMDLOAD, TXPARAMSIZE, TXPARAMCOPY follow the pattern of CALLDATA* / RETURNDATA* opcode families.

  1. TXPARAMSIZE opcode puts the byte size of the transaction parameter value defined by the input txparam_id. It takes 1 stack argument:
    • txparam_id: identifier of the queried transaction parameter.
  2. TXPARAMLOAD opcode takes the byte offset in the specified transaction parameter from stack and puts the 32-byte value starting from the given offset of the specified transaction parameter to stack.
    It takes 2 stack argument:
    • txparam_id: identifier of the queried transaction parameter.
    • offset: byte offset in the transaction parameter to copy.
  3. TXPARAMCOPY opcode copies data from the appropriate dynamically sized transaction parameter to memory.
    It takes 4 stack arguments:
    • txparam_id: identifier of the queried transaction parameter.
    • dest_offset: byte offset in the memory where the result will be copied.
    • offset: byte offset in the transaction parameter to copy.
    • size: byte size to copy.

The valid values for txparam_id are described in the table below. Note that some parameters are "optional" for AA transactions, and these parameters have default values as stated below.

txparam_idReturn valueData sizeDefaultComment
0x00current transaction type32
0x01nonce32
0x02sender32
0x03sender_validation_datadynamic
0x04deployer0 or 32address(0)
0x05deployer_datadynamicempty array
0x06paymaster0 or 32address(0)
0x07paymaster_datadynamicempty array
0x08sender_execution_datadynamic
0x09valid_after320
0x0Avalid_until322^256-1
0x0Bmax_priority_fee_per_gas32
0x0Cmax_fee_per_gas32
0x0Dsender_validation_gas_limit32
0x0Epaymaster_validation_gas_limit320
0x0Fsender_execution_gas_limit32
0x10paymaster_post_op_gas_limit320
0x11access_list hash32
0x12authorization_list hash32
0xF0current_frame_role320
0xF1tx_hash_for_signature32does not include sender_validation_data
0xF2execution_status32only role_paymaster_post_op
0xF3execution_gas_cost32only role_paymaster_post_op

Limitations on TXPARAM* opcodes

The TXPARAM* opcodes are only enabled in frames with a correct current_frame_role. Calling these opcodes in another context, or with invalid txparam_id, returns zero values and zero lengths.

current_frame_roleallowed txparam_id
0 (none)None, TXPARAM* opcodes always return zero value and zero length
role_sender_deployment, role_sender_validation, role_paymaster_validationAll tx parameters, current_frame_role, tx_hash_for_signature
role_paymaster_post_opAll tx parameters, current_frame_role, tx_hash_for_signature, execution_status, execution_gas_cost
role_sender_executionOnly current_frame_role

Contact should first call TXPARAMLOAD 0xF0 (current_frame_role) to determine the current frame role.

In case current_frame_role is not set for the current frame it has a default value of 0.

TXPARAM* opcodes gas prices

The new opcodes have gas prices equivalent to corresponding CALLDATA* opcodes:

  1. TXPARAMLOAD - static value of 3 gas

  2. TXPARAMSIZE- static value of 2 gas

  3. TXPARAMCOPY - dynamic formula

    
    

Time range validity (optional)

If the valid_until field is non-zero, the transaction is only valid for inclusion in a block with a timestamp at most valid_until value. Similarly, the transaction is only valid for inclusion in blocks with a timestamp at most the valid_after value.

Sender Deployment (optional)

Inputs to the deployer contract are not defined by the protocol and are controlled by the deployer_data parameter.

The sender deployment frame MUST result in the sender address becoming initialized with contract code.

This step is performed with the role_sender_deployment role.

Sender Validation

This step is performed with the role_sender_validation role.

In order for the transaction to be considered valid, the sender validation frame MUST return without reverting.

Paymaster Validation (optional)

This step is performed with the role_paymaster_validation role.

In order for the transaction to be considered valid, the paymaster validation frame MUST return without reverting. If it does, the Paymaster contract is charged for the transaction gas costs instead of the Sender.

Sender Execution

This step is performed with the role_sender_execution role.

Inputs to the Sender contract are not defined by the protocol and are controlled by the sender_execution_data parameter.

Paymaster post-operation frame (optional)

This step is performed with the role_paymaster_post_op role.

It is intended to provide the Paymaster contract with an opportunity to finalize any calculations after the results of the Sender Execution are known.

The execution_status and execution_gas_cost values are accessible via the TXPARAMLOAD opcode.

The post-operation frame is considered an integral part of the transaction execution phase. It means that if the post-operation frame reverts its execution, the Sender Execution state changes are also reverted.

Transaction Execution Flow

All legacy transaction types only have an implicit validation phase where balance, nonce, and signature are checked, and an implicit execution phase with a single top-level execution frame.

For all legacy transaction types, during the single top-level execution frame, the ORIGIN (0x32, tx.origin) and CALLER (0x33, msg.sender) are both equal to the address that is determined by the transaction's ECDSA signature (yParity, r, s).

When processing an EIP-7701 transaction, however, multiple execution frames will be created. The full list of possible frames and their corresponding role definitions is as follows:

  1. Validation Phase
    • sender deployment frame (once per account) - role_sender_deployment
    • sender validation frame (required) - role_sender_validation
    • paymaster validation frame (optional) - role_paymaster_validation
  2. Execution Phase
    • sender execution frame (required) - role_sender_execution
    • paymaster post-operation frame (optional) - role_paymaster_post_op

All execution frames in the Validation Phase must be completed successfully without reverting in order for the transaction to be considered valid for a given position in a block.

In all top-level frames, the global variables have the following meaning:

Opcode NameSolidity EquivalentValue
CALLERmsg.senderThe AA_ENTRY_POINT address
ORIGINtx.originThe transaction sender address
CALLDATA*msg.dataEmpty for all call frames except for the sender execution frame, for which it is set to sender_execution_data

Transaction execution context

Note that some behaviours in the EVM depend on the transaction context. These behaviours include:

  1. Costs of the SSTORE (0x55) opcode per EIP-2200
  2. Costs of accessing cold addresses and slots per EIP-2929
  3. Values available within the transient storage per EIP-1153
  4. Maximum amount of gas refund assigned after the execution per EIP-3529

These features are not affected by the separation of the transaction into multiple frames. Meaning, for example, that a value set with TSTORE (0x5D) in one frame will remain available in the next one.

Costs of accessing cold addresses for Sender, Paymaster, and Deployer

The Sender address is pre-warmed as part of the AA_BASE_GAS_COST.

When non-zero address, that is not equal to the Sender address, is provided for a Paymaster or a Deployer contract, an additional EIP-2929 COLD_ACCOUNT_READ_COST cost of 2600 gas is charged and the address is added to accessed_addresses.

Flow diagrams

Simple AA Transaction flow

Simple AA transaction flow diagram

Complete AA transaction flow

Simple AA transaction flow diagram

Pseudocode

AA transaction state transition function


Block transition function


Rationale


Introduction of the TXPARAM* opcode family

The validation calls of a Smart Contract Account code need to have full access to the majority of transaction details in order to be able to make an informed decision about either accepting or rejecting the transaction.

A small subset of this data is available with the existing opcodes, like CALLER (0x33) or GASPRICE (0x3A). However, creating an opcode for every transaction parameter is not feasible or desirable.

The TXPARAM* opcode family provides the Account Abstraction contracts with access to this data.

These values are not made accessible to the transactions' execution or to legacy transaction types. This limitation prevents the TXPARAM* opcode family from becoming a new source of a globally observable state, which could create backwards compatibility issues in the future.

Backwards Compatibility


Security Considerations


As the ACCEPTROLE opcode represent a generic way to authorize any action on behalf of the contract, correct and secure implementation of this code is critical. We expect that compilers targeting EVM will play a major role in enabling and ensuring Smart Contract Accounts' security.

For smart contract security auditors and security-oriented developer tools it is crucial to ensure that contracts not meant to have roles in AA transactions do not have unexpected ACCEPTROLE opcode. Otherwise, these contracts may present an immediate security threat.

As an example, block explorers should tag contracts as "user accounts" or "paymasters" if they have the ACCEPTROLE opcode used in their source code.

Copyright


Copyright and related rights waived via CC0.