# EIP-7701: Native account abstraction Source: https://eips.ethereum.org/EIPS/eip-7701 Kiwi News: https://news.kiwistand.com/stories/EIP-7701-Native-account-abstraction?index=0x683569fe5dcf5e1513069f2c4c80ee175c57af010fadb1abc5d9f8867333f54fc8592b4b Submitted by tim on 2025-05-27 UTC, 4 upvotes, 0 comments ## Summary EIP-7701 proposes native account abstraction for Ethereum, splitting transaction processing into validation, execution, and post-operation steps, and it is now withdrawn as superseded by EIP-8141. The proposal, authored by Vitalik Buterin, Yoav Weiss, Alex Forshtat, Dror Tirosh and Shahaf Nacson and created on 2024-05-01, uses a new transaction type and a family of opcodes. It lets one contract pay gas for a transaction executed from another contract, and it introduces CURRENT_ROLE and ACCEPT_ROLE opcodes. The specification sets AA_BASE_GAS_COST at 15000 and charges an additional 2400 gas when a non-sender Paymaster or Deployer address is provided. ## Article 🛑 Withdrawn Standards Track: Core Native Account Abstraction protocol, relying on a new transaction type and a family of opcodes Authors Vitalik Buterin (@vbuterin), Yoav Weiss (@yoavw), Alex Forshtat (@forshtat), Dror Tirosh (@drortirosh), Shahaf Nacson (@shahafn) Created 2024-05-01 Withdrawal Reason Superseded by EIP-8141 Discussion Link https://ethereum-magicians.org/t/eip-7701-native-account-abstraction/19893 Table of Contents Abstract Motivation Specification Constants New Transaction Type CURRENT_ROLE and ACCEPT_ROLE opcodes TXPARAM* opcodes Affected opcodes Costs of accessing cold addresses for Sender, Paymaster, and Deployer AA transaction processing flow Rationale Backwards Compatibility Security Considerations Copyright 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. A more detailed motivation for this proposal can be found in the README document. Specification Constants Name Value AA_TX_TYPE TBD AA_ENTRY_POINT address(0x7701) AA_BASE_GAS_COST 15000 ROLE_SENDER_DEPLOYMENT 0xA0 ROLE_SENDER_VALIDATION 0xA1 ROLE_PAYMASTER_VALIDATION 0xA2 ROLE_SENDER_EXECUTION 0xA3 ROLE_PAYMASTER_POST_OP 0xA4 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: AA_TX_TYPE || rlp([ chain_id, nonce, sender, sender_validation_data, deployer, deployer_data, paymaster, paymaster_data, sender_execution_data, max_priority_fee_per_gas, max_fee_per_gas, sender_validation_gas, paymaster_validation_gas, sender_execution_gas, paymaster_post_op_gas, access_list, authorization_list ]) CURRENT_ROLE and ACCEPT_ROLE opcodes current_context_role is a context variable set by the AA transaction to the current role. During AA transactions, it is set to the current role in the transaction’s lifecycle for each top level call. During non-AA transactions it is always set to ROLE_SENDER_EXECUTION. It remains unchanged on DELEGATECALL but is reset to ROLE_SENDER_EXECUTION on CALL / STATICCALL / CALLCODE. This behavior resembles msg.sender. The CURRENT_ROLE opcode returns the current_context_role value. The ACCEPT_ROLE opcode is equivalent to RETURN in the sense that it copies a memory slice, ends execution, and pastes the memory slice onto parent returndata, with a single modification: It accepts the frame_role as the additional input parameter, and reverts if it differs from the current_context_role For each role in the transaction’s lifecycle, a successful ACCEPT_ROLE is expected with the frame_role == role. If any validation frame failed to perform an ACCEPT_ROLE matching its role, the transaction fails the validity checks and cannot be included. TXPARAM* opcodes The TXPARAMDLOAD, TXPARAMSIZE, TXPARAMCOPY opcodes follow the pattern of CALLDATA* / RETURNDATA* opcode families. Each TXPARAM* opcode takes an extra stack input value as a first input compared to its CALLDATA* equivalent. The values of this input are as follows: n Return value Data size Default Comment 0x00 current transaction type 32 0x01 nonce 32 0x02 sender 32 0x03 sender_validation_data dynamic 0x04 deployer 0 or 32 address(0) 0x05 deployer_data dynamic empty array 0x06 paymaster 0 or 32 address(0) 0x07 paymaster_data dynamic empty array 0x08 sender_execution_data dynamic 0x0B max_priority_fee_per_gas 32 0x0C max_fee_per_gas 32 0x0D sender_validation_gas 32 0x0E paymaster_validation_gas 32 0 0x0F sender_execution_gas 32 0x10 paymaster_post_op_gas 32 0 0x11 access_list hash 32 0x12 authorization_list hash 32 0xf1 execution_status 32 See transaction scoped vars in processing flow 0xf2 execution_gas_used 32 See transaction scoped vars in processing flow 0xff tx_hash_for_signature 32 Hash of the transaction without the signature Affected opcodes In all top-level frames, the global variables have the following meaning: Opcode Name Solidity Equivalent Value CALLER msg.sender The AA_ENTRY_POINT address ORIGIN tx.origin The transaction sender address CALLDATA* msg.data Empty for all call frames except for the sender execution frame, for which it is set to sender_execution_data 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 a non-zero address that is not equal to the Sender address, is provided for a Paymaster or a Deployer contract, an additional EIP-2930 ACCESS_LIST_ADDRESS_COST cost of 2400 gas is charged and the address is added to accessed_addresses. AA transaction processing flow We define processing flow for an AA transaction as follows: def state_transition_function(tx, block, state): # Empty refunds, warm list, execution status and gas used (new), etc state.transaction_scoped_vars = {} max_gas = tx.sender_validation_gas + tx.paymaster_validation_gas + tx.sender_execution_gas + tx.paymaster_post_op_gas gas_price = min(tx.max_fee_per_gas, block.base_fee_per_gas + tx.max_priority_fee_per_gas) payer = tx.sender if tx.paymaster is None else tx.paymaster total_max_cost = max_gas * gas_price balances[payer] -= total_max_cost gas_used = 0 if get_code(tx.sender) is None: deployer_result = call(tx.deployer, [], tx.sender_validation_gas_limit, ROLE_SENDER_DEPLOYMENT) assert deployer_result.accepted_role == ROLE_SENDER_DEPLOYMENT gas_used += deployer_result.gas_used sender_result = call(tx.sender, [], tx.sender_validation_gas_limit - gas_used, ROLE_SENDER_VALIDATION) assert sender_result.accepted_role == ROLE_SENDER_VALIDATION gas_used += sender_result.gas_used if tx.paymaster: paymaster_result = call(tx.paymaster, [], tx.paymaster_validation_gas, ROLE_PAYMASTER_VALIDATION) assert paymaster_result.accepted_role == ROLE_PAYMASTER_VALIDATION gas_used += paymaster_result.gas_used checkpoint = state.take_snapshot() sender_execution_result = call(tx.sender, [], tx.sender_execution_gas, ROLE_SENDER_EXECUTION) gas_used += sender_execution_result.gas_used state.transaction_scoped_vars[execution_status] = sender_execution_result.output_code state.transaction_scoped_vars[execution_gas_used] = gas_used if tx.paymaster: postop_result = call(tx.paymaster, [], tx.paymaster_post_op_gas, ROLE_PAYMASTER_POST_OP) gas_used += postop_result.gas_used if postop_result.accepted_role != ROLE_PAYMASTER_POST_OP: state.revert_snapshot(checkpoint) balances[payer] += gas_price * (max_gas - gas_used) Rationale A full list of rationales for the decisions made in this proposal can be found in the README document. Backwards Compatibility Security Considerations As the ACCEPT_ROLE 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 ACCEPT_ROLE 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 ACCEPT_ROLE opcode used in their source code. Copyright Copyright and related rights waived via CC0. Citation Please cite this document as: Vitalik Buterin (@vbuterin), Yoav Weiss (@yoavw), Alex Forshtat (@forshtat), Dror Tirosh (@drortirosh), Shahaf Nacson (@shahafn), "EIP-7701: Native Account Abstraction [WITHDRAWN]," Ethereum Improvement Proposals, no. 7701, May 2024. Available: https://eips.ethereum.org/EIPS/eip-7701.