diff --git a/RIPS/rip-7560.md b/RIPS/rip-7560.md new file mode 100644 index 0000000..338d436 --- /dev/null +++ b/RIPS/rip-7560.md @@ -0,0 +1,878 @@ +--- +rip: 7560 +title: Native Account Abstraction +description: An account abstraction proposal that introduces consensus-layer protocol changes, instead of relying on higher-layer infrastructure. +author: Vitalik Buterin (@vbuterin), Yoav Weiss (@yoavw), Alex Forshtat (@forshtat), Dror Tirosh (@drortirosh), Shahaf Nacson (@shahafn) +discussions-to: https://ethereum-magicians.org/t/rip-7560-native-account-abstraction/16664 +status: Draft +type: Standards Track +category: Core +created: 2023-09-01 +requires: 4337, 6780 +--- + +## Abstract + +Combining the [EIP-2938](./eip-2938) +and [ERC-4337](./eip-4337) +into a comprehensive Native Account Abstraction proposal. + +We propose splitting the Ethereum transaction scope into multiple steps: validations, execution, +and post-transaction 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 contract B to pay gas for a transaction that will be executed from account contract A. + +The benefits are in backward compatibility with the emerging ERC-4337 ecosystem while achieving the +long-term goal of Native Account Abstraction. + +## Motivation + +ERC-4337 can do a lot as a purely voluntary ERC. However, any of the out-of-protocol ways of achieving +Account Abstraction faces several drawbacks compared to native support. There are a few key areas where +it is weaker than a truly in-protocol solution: + +* Existing users cannot benefit from it or upgrade to use it without moving all their assets and activity + to a new account. + +* Extra gas overhead of ~42k for a basic `UserOperation` compared to ~21k for a basic transaction. + +* Less benefit from in-protocol censorship resistance techniques such as crLists, which target transactions + and would miss `UserOperations`. + +* Relying on a significantly smaller set of participating nodes and non-standard RPC methods like + `eth_sendRawTransactionConditional`. + +* Inability to use `tx.origin` or contracts that rely on it as it returns the meaningless address of a bundler. + +EIP-2938 defines a very mature alternative approach to Account Abstraction. However, it does not translate +well to the architecture of ERC-4337 that is being used in production without any protocol changes. +Therefore, the implementation of EIP-2938 will not benefit as much from the production experience gained by using +ERC-4337 and from maintaining backward compatibility with it. + +There is also a possibility that at some point in the future, the EOAs on Ethereum will be replaced with pre-deployed +smart contracts. This, however, is impossible without an addition of Native Account Abstraction to the protocol. + +## Specification + +### Constants + +| Name | Value | +|-----------------------|---------------------------------------------------------------------------------| +| FORK_BLOCK | TBD | +| AA_TX_TYPE | 4 | +| AA_ENTRY_POINT | `address(7560)` | +| AA_SENDER_CREATOR | `address(ffff7560)` | +| AA_NONCE_MANAGER | TODO | +| AA_BASE_GAS_COST | 15000 | +| AA_ECRECOVER_COST | 6000 | +| VERSION | 1 | +| MAGIC_VALUE_SENDER | 0xbf45c166 // bytes4(keccak256("validateTransaction(uint256,bytes32,bytes)")) | +| MAGIC_VALUE_PAYMASTER | 0xe0e6183a // bytes4(keccak256("validatePaymasterTransaction(uint256,bytes32,bytes)")) | +| MAX_CONTEXT_SIZE | 65536 | +| UNUSED_GAS_PENALTY | 10 | + +### New Transaction Type + +A new [EIP-2718](./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: + +``` + +0x04 || 0x00 || rlp([ + chainId, sender, nonce, builderFee, + callData, paymasterData, deployerData, + maxPriorityFeePerGas, maxFeePerGas, + validationGasLimit, paymasterGasLimit, callGasLimit, + accessList, signature +]) + +``` + +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. + +If `paymasterData` is specified, its first 20 bytes contain the address of a `paymaster` contract. + +If `deployerData` is specified, its first 20 bytes contain the address of a `deployer` contract. + +### Optional "transaction counter header" + +In some cases the block builders may want to split up an array of type `AA_TX_TYPE` transactions into individual +batches of transactions that perform validations and executions separately. + +Without a header transaction type this would only be possible by creating an artificial legacy type transaction. +Instead, we propose to introduce an explicit "counter" transaction subtype. + +Their payload should be interpreted as: + +``` +0x04 || 0x01 || rlp([chainId, transactionCount]) +``` + +Header transactions have a unique hash calculated as follows: + +``` +keccak256(AA_TX_TYPE || 0x01 || rlp(chainId, transactionCount, blockNumber, txIndex)) +``` + +The `blockNumber` and `txIndex` parameters are added to the hash to achieve unique header transaction IDs. + +The header transactions are only used to help execution clients determine how many of the `AA_TX_TYPE` transactions +belong to each individual batch. +The block is not valid if a header transaction is located anywhere except before an `AA_TX_TYPE` transactions.\ +If a header transaction is included all `AA_TX_TYPE` transactions in the block must be covered by one. + +Header transactions do not affect blockchain state and do not cost any gas. + +### Non-sequential nonce support + +Before RIP-7560, for accounts with associated code (smart contracts), the account nonce is only used and incremented +when the account executes the `CREATE` (`0xf0`) opcode. + +However, with Smart Contract Accounts this creates a bottleneck for some use-cases. +For example, an account that is operated by multiple participants simultaneously will require these participants +to coordinate their transactions to avoid invalidating each other. + +Another example when this can also be a limitation is a case where there are separate execution flows. +A configuration change may require multiple participants to co-sign a transaction but a regular operation does not. +With sequential nonces, all operations will have to be halted until the configuration change is executed. + +To address it we propose an introduction of a separate 2-dimensional nonce used when contracts initiate a transaction. + +The `nonce` parameter of the transaction is to be interpreted as `uint192 key || uint64 seq` value. +The contract account nonce is then defined as a mapping `address account => uint192 key => uint64 seq`. +This approach guarantees unique transaction nonce and hash but removes the requirement of nonce being sequential +numbers. + +This `nonce` is exposed to the EVM in a `NonceManager` pre-deployed contract located at the AA_NONCE_MANAGER address. + +The `nonce` is [validated and incremented](#nonce-validation-frame) on-chain before the rest of the validation code. + +The old `nonce` account parameter remains in use for transactions initiated by EOAs and for the `CREATE` opcode. + +#### NonceManager Pseudocode + +``` + +if evm.caller == AA_ENTRY_POINT: + validate_increment() +else: + get() + +def get(): + if len(evm.calldata) != 44: + evm.revert() + + // address sender, uint192 key + address = to_uint160_be(evm.calldata[0:20]) + key = to_uint192_be(evm.calldata[20:44]) + + nonce = storage.get(keccak(address, key)) + + evm.return((key << 64) + nonce) + +def validate_increment(): + + address = to_uint160_be(evm.calldata[0:20]) + key = to_uint192_be(evm.calldata[20:44]) + nonce = to_uint64_be(evm.calldata[44:52]) + + current_nonce = storage.get(keccak(address, key)) + + if (nonce != current_nonce): + evm.revert() + + storage.set(kecca + k(address, key), current_nonce + 1) + +``` + +#### NonceManager Bytecode and deployment + +TODO. + +### Gas fees are charged directly from the contract balance + +The maximum gas cost of the AA_TX_TYPE transaction is defined as: + +``` + +maxPossibleGasCost = AA_BASE_GAS_COST + + callGasLimit + + paymasterGasLimit + + validationGasLimit + +``` + +If `paymaster` is not specified, the `maxPossibleGasCost` is charged up-front, before any computation is done in any +execution frame, from the balance of the `sender` address. +If `paymaster` is specified, the gas cost is charged from its balance. +The transaction is invalid if the balance of the account that is being pre-charged, +whether it is a `sender` or a `paymaster`, is insufficient. +After the transaction finishes its execution, the address that was pre-charged may receive a gas refund. + +### Gas fees charged for transaction input + +For all the existing transaction types, G_txdatazero (4 gas) and G_txdatanonzero (16 gas) per byte is +charged for the `data` parameter. + +Transaction Type AA_TX_TYPE introduces the following dynamic length inputs: `callData`, `paymasterData`, +`deployerData`, `signature`. Each of these parameters' gas cost is counted towards transaction data cost. +This transaction data gas cost is referred to as `calldataCost` and is subtracted from the `validationGasLimit` +before execution of the transaction. +The transaction is considered INVALID if `validationGasLimit` is smaller than `calldataCost`. + +### Builder Fee + +As we need to account for an additional off-chain work that block builders have to perform to +include `AA_TX_TYPE` transactions in their blocks, as well as a potential L1 gas cost for builders +operating on L2 rollups, and given that this work does not correspond to the amount of gas spent on +validation and is not linked to the gas price, the `sender` may decide +to pay an extra `builderFee` as a "tip" to the block builder. + +This value is denominated in wei and is passed from the `sender`, or the `paymaster` if it is specified, +to the `coinbase` of the current block as part of the gas pre-charge. + +### Unused gas penalty charge + +Transactions of type `AA_TX_TYPE` that reserve a lot of gas for themselves using `validationGasLimit`, +`paymasterGasLimit` and `callGasLimit` fields but do not use the reserved gas present a challenge for +block builders. This is especially demanding in case a gas used by a transaction can be significantly different +based on its position within a block, as such transactions may cause the block builder to iterate its algorithm +many times until a fully utilized block is discovered. + +A penalty of `UNUSED_GAS_PENALTY` percent of the entire unused gas limit is charged from the +transaction `sender` or `paymaster`. + +The total gas limit is calculated as `totalLimit = validationGasLimit + paymasterGasLimit + callGasLimit`.\ +The `totalGasUsed` is calculated as a sum of all gas used during the transaction.\ +The unused gas is calculated as `unusedGas = totalLimit - totalGasUsed`. + +### Multiple execution frames for a single transaction + +All existing transaction types only have an implicit validation phase where balance, nonce, and signature are checked, +and a single top-level execution frame with +`tx.origin == msg.sender` which is the address that is determined by a transaction ECDSA signature. + +When processing a transaction of type `AA_TX_TYPE`, however, multiple execution frames will be created. +The full list of possible frames tries to replicate the ERC-4337 flow: + +1. Validation Phase + * `nonce` validation and increment frame (required) + * `sender` deployment frame (once per account) + * `sender` validation frame (required) + * `paymaster` validation frame (optional) +2. Execution Phase + * `sender` execution frame (required) + * `paymaster` post-transaction frame (optional) + +All execution frames in the "Validation Phase" must be completed successfully without reverting, and the return value +for `sender` and `paymaster` validation frames must include `MAGIC_VALUE_SENDER` and `MAGIC_VALUE_PAYMASTER` accrodingly +in order for the transaction to be considered valid for a given position in a block. + +In terms of block validity, all validation and execution frames may read and write any state when included in the block. +However, the AA transactions in the mempool SHOULD be bound by storage access rules to avoid DoS on block builders. +These rules are defined in [ERC-7562](./eips/eip-7562). + +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. `AA_SENDER_CREATOR` for the "deployment frame". | +| `ORIGIN` | `tx.origin` | The transaction `sender` address | +| `CALLDATA*` | `msg.data` | The transaction data is set to inputs of the corresponding frame | + +#### Nonce validation frame + +The `NonceManager` is invoked with the following data: + +```solidity +abi.encodePacked(sender, nonce) +``` + +#### Sender deployment frame + +The `deployer` address is invoked with the `deployerData[20:]` as call data input. +It is important that the `deployer` is **not** invoked from the `AA_ENTRY_POINT` but from the `AA_SENDER_CREATOR`. +This is necessary to guarantee that `AA_ENTRY_POINT` may never initiate a call to a `sender` execution function +without first completing a successful validation. + +The gas limit of this frame is set to `validationGasLimit`. +The amount of gas used by this frame is referred to as `senderCreationGasUsed`. + +The sender deployment frame MUST result in the `sender` address becoming +initialized with contract code. + +#### Sender validation frame + +We define the following Solidity struct to represent the AA transaction on-chain: + +```solidity + +struct TransactionType4 { + address sender; + uint256 nonce; + uint256 validationGasLimit; + uint256 paymasterGasLimit; + uint256 callGasLimit; + uint256 maxFeePerGas; + uint256 maxPriorityFeePerGas; + uint256 builderFee; + bytes paymasterData; + bytes deployerData; + bytes callData; + bytes signature; +} + +``` + +We then define the following Solidity method and the `sender` of the transaction is invoked with the corresponding data: + +```solidity + +function validateTransaction(uint256 version, bytes32 txHash, bytes transaction) external returns (uint256 validationData); + +``` + +The gas limit of this frame is set to `validationGasLimit - senderCreationGasUsed - calldataCost`.\ +The `transaction` parameter is interpreted as an ABI encoding of `TransactionType4`.\ +The `txHash` parameter represents the hash of the AA_TX_TYPE transaction with empty signature, as defined in section +[Calculation of Transaction Type AA_TX_TYPE hash](#calculation-of-transaction-type-aatxtype-hash).\ +The `version` parameter is added in order to maintain the Solidity method ID in case of changes to this struct +in future revisions of this EIP. + +The amount of gas used by this frame is referred to as `senderValidationGasUsed`. + +The frame must return 32 bytes `validationData` that is interpreted as: + +```solidity + +abi.encodePacked(MAGIC_VALUE_SENDER, validUntil, validAfter) + +``` + +In order to allow a gas estimation to determine the amount of gas that this frame +requires to complete successfully while not having the actual `signature` value, this function +should avoid reverting on invalid signature, and should return a value different from `MAGIC_VALUE_SENDER`. + +Type of the `validUntil` is 6-byte timestamp value, or zero for "infinite". The transaction is valid only up to this time. +Type of the `validAfter` is 6-byte timestamp. The transaction is valid only after this time. + +The `validateTransaction` function can choose to revert on any condition that can be satisfied during gas estimation. + +#### Paymaster validation frame + +The `paymaster` of the transaction, if specified, is invoked with the following data: + +```solidity + +function validatePaymasterTransaction(uint256 version, bytes32 txHash, bytes transaction) external returns (bytes context, uint256 validationData); + +``` + +The gas limit of this frame is set to `paymasterGasLimit`. + +The amount of gas used by this frame is referred to as `paymasterValidationGasUsed`. + +The `transaction` parameter is interpreted as an ABI encoding of `TransactionType4`.\ +The `txHash` parameter represents the hash of the AA_TX_TYPE transaction with empty signature, as defined in section +[Calculation of Transaction Type AA_TX_TYPE hash](#calculation-of-transaction-type-aatxtype-hash). + +The frame must return a bytes array that is interpreted as: + +```solidity + +abi.encode(context, MAGIC_VALUE_PAYMASTER, validUntil, validAfter) + +``` + +Same as in the [`sender` validation frame](#sender-validation-frame), in order to support gas estimation this +frame should return a value different from `MAGIC_VALUE_PAYMASTER` for conditions that cannot be satisfied +before signing. + +The size of the `context` byte array may not exceed `MAX_CONTEXT_SIZE` for a transaction to be considered valid. + +#### Sender execution frame + +The `sender` address is invoked with `callData` input. + +The gas limit of this frame is set to `callGasLimit`.\ +Calculation of the `calldataCost` value is defined in the +[Gas fees charged for transaction input](#gas-fees-charged-for-transaction-input) section.\ +The amount of gas used by this frame is referred to as `gasUsedByExecution`. + +The validation frames do not revert if the execution frame reverts. +The `postPaymasterTransaction` may still be called with a `success: false` flag. + +#### Paymaster post-transaction frame + +After the sender execution frame is over the `paymaster` may need to perform some post-transaction logic, +for instance to perform some kind of cleanup or bookkeeping. +If the gas payment validation returned a non-zero `context`, the `paymaster` is invoked again +with the following inputs: + +```solidity + +function postPaymasterTransaction(bool success, uint256 actualGasCost, bytes context) external; + +``` + +The `actualGasCost` parameter is the actual amount paid by the paymaster for this transaction, +and `success` indicates whether this transaction's execution frame completed without revert. + +The gas limit of this frame is set to `paymasterGasLimit - paymasterValidationGasUsed`. + +Revert in the `postPaymasterTransaction` frame reverts the transaction's execution frame as well. +The validation frames do not revert if the `postPaymasterTransaction` frame reverts. +The gas fees charged from the `paymaster` will still include the gas cost of the reverted execution frame. + +### Execution flow diagram + +The execution flow determined by an Account Abstraction Transaction is visualised by the following flow diagram: + +![](../assets/rip-7560/flow_diagram.png) +*Execution flow for the Native Account Abstraction Transactions* + +### Execution layer transaction validation + +On the execution layer, the transaction validity conditions for a block are extended as follows: + +``` + +func validateAccountAbstractionTransaction(tx *Transaction) { + assert !(sender.code.length > 0 && deployerData.length > 0) + + if (sender.code.length == 0 && deployerData.length == 0) { + validUntil = (nonce >> 112) & 0xffffffffffff + validAfter = (nonce >> 160) & 0xffffffffffff + assert Date.now() <= validUntil + assert Date.now() >= validAfter + } + + if (sender.code.length == 0 && deployerData.length > 0) { + assert deployerData.length >= 20 + deployer := deployerData[0:20] + calldataCost := calculateCalldataCost(tx) + retDeployer, error := evm.Call( + from: AA_SENDER_CREATOR, + to: deployer, + input: deployerData[20:], + gas: validationGasLimit - calldataCost) + assert error == nil + assert sender.code.length > 0 + } + + if (paymasterData.length > 0) { + assert paymasterData.length >= 20 + paymaster := paymasterData[0:20] + paymasterInput := ABI.encodeWithSelector('validatePaymasterTransaction', tx, tx.hash) + retPaymaster, error := evm.Call( + from: AA_ENTRY_POINT, + to: paymaster, + input: paymasterInput, + gas: paymasterGasLimit) + assert error == nil + assert Date.now() <= retPaymaster.validUntil + assert Date.now() >= retPaymaster.validAfter + assert retPaymaster.isValid + } + + if (sender.code.length == 0) { + signer := ecrecover(tx.hash, tx.signature) + assert signer == sender.address + } else { + senderInput := ABI.encodeWithSelector('validateTransaction', tx, tx.hash); + retSender, error := evm.Call( + from: AA_ENTRY_POINT, + to: sender, + input: senderInput, + gas: validationGasLimit - retDeployer.gasUsed) + assert error == nil + assert Date.now() <= retSender.validUntil + assert Date.now() >= retSender.validAfter + assert retSender.isValid + } +} + +``` + +In order to defend from DoS attack vectors, the block builders performing mempool transaction validation SHOULD consider +the opcode banning and storage access rules described in ERC-7562. + +[Block validation](#execution-layer-block-validation) takes roughly the same amount of work as without AA transactions. +In any case, validation must execute the entire block in order to verify the state change. +During this execution, it currently verifies signatures, nonces, and gas payment. +With Account Abstraction, it will also verify that all the validation frames were successful. +There is a slight increase in required memory mostly used to store the `context` value that is passed from +the `paymaster` validation frame to its post-transaction frame. + +As long as all transaction validation steps return correct values the block is considered valid. +Block builders who are willing to relax the rules applied to the validation frames MAY do so. + +Such transactions MUST NOT be propagated through the default transaction mempool as they will be rejected by the nodes +and the sending node will be blocked as a spammer. +They may be propagated in the alternative mempool that allows them explicitly as defined in ERC-7562. + +### All validation state changes apply before all execution ones + +Filling a block with AA transactions must not be a challenge for the block builder. +However, if each transaction during its execution can alter any state that affects the validity of another transaction +in the mempool, the block builder will be forced to revalidate all transactions in the mempool after each inclusion. + +We mitigate that by applying all changes in all the validation frames of a sequence of AA transactions first +and all execution frames apply immediately after that. + +In theory, the validation frames can also invalidate each other, but we define ways to prevent that by applying +certain rules for the mempool transactions in ERC-7562. + +A builder that chooses not to enforce the rules from ERC-7562 **must** take care to re-validate each transaction +against the mid-block state at the position where it is being included into a block. +Otherwise, the resulting block is likely to end up being invalid. + +### Block structure diagram + +Here is a visual representation of a block that contains multiple Account Abstraction Transactions. +The validation parts of AA transactions are executed as separate transactions, +but are not represented as separate transactions in the block data. + +![](../assets/rip-7560/block_overview.png) +*The structure of a block containing multiple Native Account Abstraction Transactions* + +Zooming into a single transaction, the validation part of an AA transaction may include multiple exectution frames: + +![](../assets/rip-7560/zoom_into_transaction.png) +*Frames within a single Native Account Abstraction Transaction within a block* + +### Validation state change virtual transactions + +The validation frames of the AA_TX_TYPE transaction are represented as individual virtual transactions by the clients. +They are assigned their own sequential `transactionIndex`, and their `transactionHash` is defined as +(`AA_TX_TYPE transaction hash + 1`). + +All block-related RPC methods, like `eth_getBlockByHash` and `eth_getBlockByNumber`, must include these virtual +transactions as part of the `transactions` field and include validation in the block transaction count. + +All transaction-related RPC methods, like `eth_getTransactionByHash` and `eth_getTransactionReceipt`, must +accept the virtual transaction hash as input and return the details calculated as if the validation was a +separate transaction. + +There is a number of behaviours that define transaction-wide effects in Ethereum. +This list includes, but is not limited to: + +* Tracking `accessed_addresses` +* [EIP-1283](./eip-1283) Gas metering for SSTORE +* [EIP-1153](./eip-1153) Transient storage opcodes + +Any such behaviour has separate effects in the "Validation Virtual Transaction" and "Execution Transaction". + +Gas refunds are issued at the end of the entire transaction only. + +### Transaction validity time range parameters + +The `Paymaster validation frame` and the `Sender validation frame` each return values `validUntil` and `validAfter`. +If the transaction is initiated by an EOA, these fields may be encoded into unused bits of the `nonce`. + +These values allow the `sender` and `paymaster` contracts to specify +a time range for the blocks the transaction will be valid for. + +Transaction cannot be included in a block outside of this time range. +If included, such a block is considered invalid. + +Passing `validUntil = 0` and `validAfter = 0` disables the check. + +### Calculation of Transaction Type AA_TX_TYPE hash + +``` + +keccak256(AA_TX_TYPE || 0x00 || rlp(transaction_payload) + +``` + +Note that the `chainId` and `accessList` parameters are included in the transaction hash calculation but are not +available on-chain as part of the `TransactionType4` struct. + +In order to calculate the transaction hash that will be used during the signing of the transaction and validation of +the transaction signature by the `sender`, the value of the `signature` parameter is considered to be an empty +byte array. + +### Accepting EOA account as `sender` to achieve native gas abstraction + +In case the `sender` address does not have any code deployed and the `deployerData` length is zero, +interpret the `signature` parameter as `(y_parity, r, s)` and the `nonce` parameter +as `(validUntil, validAfter, nonce)`. +Replace the sender validation frame with default ECDSA signature validation. +Also check the block timestamp is within the `[validUntil, validAfter]` range. + +The base transaction gas cost, in this case, is increased by `AA_ECRECOVER_COST`. + +The `callData` parameter in this case is interpreted as following: + +``` + +target || value || data + +``` + +### Execution layer block validation + +When validating a block, the validity conditions for a block are extended as follows: + +``` + +for txIndex := 0; txIndex < range block.Transactions.Len(); txIndex++ { + + // 1. Save the current transaction + txCurr = block.Transactions[txIndex] + + if (txCurr.Type() == AccountAbstractionTransaction) { + + // 2. Start running validations for AA transactions + for j := txIndex; j < range block.Transactions().Len(); j++ { + tx = block.Transactions[j] + + // 3. Stop after encountering a non-AA transaction (or reaching the end of the block) + if (tx.Type() != AccountAbstractionTransaction) { + break + } + context[j], paymasterValidationGasUsed[j], error := validateAccountAbstractionTransaction(tx) + assert error == nil + } + + // 4. If all validations are successful, go back to the saved tx index and run all executions + for j := txIndex; j < range block.Transactions().Len(); j++ { + tx = block.Transactions[j] + if (tx.Type() != AccountAbstractionTransaction) { + break + } + + retCall, error := evm.Call( + from: AA_ENTRY_POINT, + to: sender, + input: callData, + gas: callGasLimit) + + txIndex := j // transaction executed - no need to revisit in the outer loop + + + // 5. Run paymaster's post-transaction logic if necessary + if (context[j].Len() == 0){ + continue + } + + paymasterPostTransactionInput := ABI.encodeWithSelector('postPaymasterTransaction', success, actualGasCost, context[j]) + retPostTransaction, error := evm.Call( + from: AA_ENTRY_POINT, + to: paymaster, + input: paymasterPostTransactionInput, + gas: paymasterGasLimit - paymasterValidationGasUsed[j]) + } + } + else { + // handle other types of transactions + evm.Apply(txCurr) + } +} + +``` + +### RPC methods (eth namespace) + +#### `eth_sendTransaction` and `eth_sendRawTransaction` + +Accepts Transaction Type `AA_TX_TYPE`. + +Return values unchanged for a successful call. + +In case of failure, MUST return an error result object, with code and message. +The error code and message SHOULD be set as follows: + +* code: -32500 - transaction validation failed by `sender`. + The message field SHOULD be set to the revert message from the `sender`. + +* code: -32501 - transaction validation failed by `paymaster`. + The message field SHOULD be set to the revert message from the `paymaster`. + +* code: -32502 - transaction rejected because of storage or opcode rules violation in a validation frame. + The message field SHOULD be set to the location and description of the violated rule. + +* code: -32503 - Transaction out of time range. + +* code: -32504 - transaction rejected because `paymaster` is throttled or banned, as defined by ERC-7562. + +* code: -32505 - transaction rejected because `factory` is throttled or banned. + +* code: -32506 - transaction rejected because `sender` is throttled or banned. + +#### `eth_signTransaction` + +Accepts Transaction Type `AA_TX_TYPE`. + +Returns the RLP-encoded transaction object with value for the `signature` field that makes the `AA_TX_TYPE` +transaction valid. + +Returns error object if this operation cannot be performed by the RPC endpoint. + +#### `eth_getTransactionReceipt` + +Accepts the hash of a virtual transaction that encapsulates the validation frames of the `AA_TX_TYPE` transaction. +This transaction's ID is defined as (`AA_TX_TYPE transaction hash + 1`). + +If an AA transaction is included in a block, returns the following values in addition to the existing fields: + +| Name | Value | +|----------------------------|------------------------------------------------------------------------------| +| sender | Address of the sender of this transaction | +| nonce | The transaction nonce value | +| paymaster | Address of the Paymaster if it is paying for the transaction, null otherwise | +| deployer | Address of the Deployer if it is included in the transaction, null otherwise | +| senderCreationGasUsed | The amount of gas actually used by the sender deployment frame | +| senderValidationGasUsed | The amount of gas actually used by the sender validation frame | +| paymasterValidationGasUsed | The amount of gas actually used by the paymaster validation frame | + +Accepts hash of Transaction Type `AA_TX_TYPE`. + +If an AA transaction is included in a block, returns the following values in addition to the existing fields: + +| Name | Value | +|---------------------------------|------------------------------------------------------------------------------------------------| +| status | Either 1 (success) or 0 (failure) status of the execution frame | +| executionGasUsed | The amount of gas actually used by the execution frame | +| postPaymasterTransactionStatus | Either 1 (success), 0 (failure), or `null` (did not run) status of the `postPaymasterTransaction` frame | +| postPaymasterTransactionGasUsed | The amount of gas actually used by the paymaster `postPaymasterTransaction` frame | + +Note that the field `to` is not included as there is no clear `target` in an `AA_TX_TYPE` transaction. + +#### `eth_call` + +Accepts Transaction Type `AA_TX_TYPE` with all fields except `from` and `callData` optional. + +Returns the return value of [the `sender` execution frame](#sender-execution-frame). + +If provided with `paymasterData` and `deployerData` also executes the corresponding frame. + +If any of the frames reverts the call returns the revert data of each reverted frame. + +#### `eth_estimateGasAccountAbstraction` + +Accepts Transaction Type `AA_TX_TYPE` with fields `validationGasLimit`, `paymasterGasLimit`, `callGasLimit` optional. + +Optionally accepts the State Override Set to allow users to modify the state during the gas estimation. +This field as well as its behavior is equivalent to the ones defined for `eth_call` RPC method. + +Returns `{validationGasLimit, paymasterGasLimit, callGasLimit, builderFee}` object. + +Note that the `deployerData` and `paymasterData` fields are required for a consistent result. + +As mentioned earlier, the `sender` and `paymaster` contracts should not revert on the validation failure +and should return a value different from `MAGIC_VALUE_SENDER` or `MAGIC_VALUE_PAYMASTER` accordingly +in order to enable gas estimation. + +One acceptable way to achieve this behavior for Smart Contract Accounts is to compare the `signature` parameter to +a predetermined "dummy signature" and to return without reverting in case the values match. +This will not result in transaction being authorized as long as returned value does not include `MAGIC_VALUE_SENDER`. + +## Rationale + +### Using Solidity method selectors in a Core EIP + +The contracts that have a role in this Account Abstraction proposal, such as `sender` or `paymaster`, +MUST know which code to execute and understand the calldata provided to them in order to validate the transaction. + +We argue that the most straightforward implementation is to rely on Solidity 4-byte method selectors as it is an +established de-facto standard. + +### Accepting `AA_TX_TYPE` transactions from EOAs + +While it may seem like allowing EOAs to initiate `AA_TX_TYPE` transactions contradicts the purpose of Account Abstraction, we argue that this +may actually be important for the adoption of Smart Contract Accounts. + +It will enable all existing EOAs to benefit from the improved UX features like gas abstraction and validity ranges. + +In the future, this can be used to pay gas for transactions that add code to the EOA addresses, +once Ethereum implements changes like the ones proposed in +[EIP-5003: Insert Code into EOAs with AUTHUSURP](./eip-5003), +[EIP-6913: SETCODE instruction](./eip-6913) and +[EIP-7377: Migration Transaction](./eip-7377). + +## Backwards Compatibility + +This EIP preserves most of the design elements established by the ERC-4337. This allows the same client code and smart +contracts to be used in both systems with minimal to no modifications, while providing significant UX improvements. + +Existing contracts are not significantly affected by the change. +The assumption that `tx.origin` is guaranteed to be an EOA is no longer valid. +The assumption that `tx.origin` is the address that pays for the current transaction is no longer valid as well. + +Any code that expects a single top-level execution frame for an Ethereum transaction will have to accommodate +the new transaction type. + +[EIP-3607](./eip-3607) introduces a ban on transactions from senders with deployed code. +This limitation does not apply to AA_TX_TYPE transactions. + +### Migration path for existing ERC-4337 projects and further roadmap + +#### Existing bundlers can co-exist on the network + +The ERC-4337 is not a protocol change and may remain operational in parallel to this EIP indefinitely. +Given the similarity to ERC-4337, the same block builders may easily support both ERC-4337 and `AA_TX_TYPE` transactions. + +#### Accounts need to upgrade their `EntryPoint` to an adapter contract + +The team behind ERC-4337 will provide a reference implementation of a contract converting +the ABI of the `paymaster` and `sender` contracts. This adapter can be set as a trusted +`EntryPoint` address by the ERC-4337 contracts. + +#### Supporting ERC-4337 RPC calls as a compatibility layer + +The `sender` contracts MAY support both ERC-4337 and `AA_TX_TYPE` transactions during a transition period, +as long as this EIP may be adopted by some chains and not by others. + +## Security Considerations + +This EIP creates a complex and sophisticated mechanism and aims to expand the usage of Smart Contract Accounts. +All of it creates a lot of new risk vectors and attack surfaces. + +The following is a non-exhaustive list of known security considerations regarding Native Account Abstraction. + +### Attacks on validation-execution separation + +The state that exists at the end of the validation frame may be observed or modified by unrelated contracts before +the execution frame begins. +`Sender` contracts must take great care in making sure their code does not make any false assumptions. + +### DoS attacks on block builders + +The amount of computation and available memory that is necessary to maintain a mempool and produce valid blocks is +increased significantly. + +### Directly charging the balance of a contract + +This EIP adds a new way for a smart contract to have its balance charged simply by returning a valid value from a +function with method ID that corresponds to `validateTransaction`, `validatePaymasterTransaction`. + +This creates a new kind of risk for contracts that accidentally or maliciously contain such methods but are not public +about the fact that these contracts can be used as a `sender` or a `paymaster` in an `AA_TX_TYPE` transaction. + +This is somewhat mitigated by requiring these contracts to return `MAGIC_VALUE_SENDER` or `MAGIC_VALUE_PAYMASTER`, +however code reviewers should still be aware of this. + +### Observing revert reasons in a validation frame + +Existing transaction types get included in a block even if reverted and provide a revert reason for debugging purposes. +There is a very short list of things that can cause a transaction not to be included on-chain: + +* low gas fee +* insufficient balance +* invalid nonce +* censorship + +This is not the case for reverts that occur in the validation phase of an `AA_TX_TYPE` transaction. +In order to address this developers should track the validity of these transactions being signed and are encouraged +to rely on the `validUntil` time range parameter to guarantee a transaction that has not been included in the intended time +will not become valid again unexpectedly for the user who had sent it. + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md). diff --git a/assets/rip-7560/block_overview.png b/assets/rip-7560/block_overview.png new file mode 100644 index 0000000..ae3db3a Binary files /dev/null and b/assets/rip-7560/block_overview.png differ diff --git a/assets/rip-7560/flow_diagram.png b/assets/rip-7560/flow_diagram.png new file mode 100644 index 0000000..eceb86c Binary files /dev/null and b/assets/rip-7560/flow_diagram.png differ diff --git a/assets/rip-7560/zoom_into_transaction.png b/assets/rip-7560/zoom_into_transaction.png new file mode 100644 index 0000000..4969014 Binary files /dev/null and b/assets/rip-7560/zoom_into_transaction.png differ