-
Notifications
You must be signed in to change notification settings - Fork 2
Change the restrictions to be programmable #23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
ded5234
cd10ab4
33f2543
e8f4829
9e90e2b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,7 @@ | |
| eip: 7906 | ||
| title: Restricted Behavior Transaction Type | ||
| description: A transaction type that provides a way for senders to restrict the outcomes of their execution | ||
| author: Alex Forshtat (@forshtat), Shahaf Nacson (@shahafn), Dror Tirosh (@drortirosh) | ||
| author: Alex Forshtat (@forshtat), Shahaf Nacson (@shahafn), Dror Tirosh (@drortirosh), Yoav Weiss (@yoavw) | ||
| discussions-to: https://ethereum-magicians.org/t/eip-restricted-behavior-transaction-type/23130 | ||
| status: Draft | ||
| type: Standards Track | ||
|
|
@@ -12,46 +12,68 @@ | |
|
|
||
| ## Abstract | ||
|
|
||
| This proposal allows the transaction payload to define write protections for balances and storage slots that are to be enforced on the consensus level. | ||
| These protected transactions empower Ethereum users to restrict the behavior of the deployed on-chain smart contracts without needing to perform a deep analysis of the EVM code. | ||
| This proposal allows the transaction payload to define write protections for balances and storage slots that are enforced on the protocol level. | ||
| These protected transactions empower Ethereum users to restrict the behavior of the deployed on-chain smart contracts without needing to perform a deep analysis of their EVM bytecode. | ||
|
|
||
| ## Motivation | ||
|
|
||
| The total value of crypto assets that have been stolen to date allegedly exceeds the yearly GDP of a medium-sized nation. | ||
| The total value of crypto assets that have been stolen to date exceeds the yearly GDP of a medium-sized nation. | ||
| This level of loss and waste is indefensible and has a long list of negative consequences for everyone involved. | ||
|
|
||
| Specifically, one of the major ways in which Ethereum users end up losing their funds is not exposing private keys, | ||
| but instead being tricked into signing transactions that appear innocent in their Wallet applications but in practice | ||
| perform a complete sweep of the senders' assets. | ||
|
|
||
| This situation is largely a result of two factors and must be addressed urgently. | ||
| The ability of an average user or a Wallet application to find, collect, review, and analyze the EVM code the transaction will execute is very limited. | ||
|
|
||
| First, the ability of an average user to find, review, and analyze the code the transaction will execute is very limited. | ||
| Second, the ability of a Wallet application to autonomously and reliably analyze this information is even more limited. | ||
|
|
||
| This means that users have no mechanism to enforce any limits on what transactions will actually do once they are signed, | ||
| and leaves a vast majority of users forced to perform blind signing in order to interact with Ethereum, | ||
| This leaves the users with no mechanism to enforce any limits on what transactions will actually do once they are signed, | ||
forshtat marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| and a vast majority of users are forced to perform blind signing in order to interact with Ethereum, | ||
forshtat marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| exposing them to significant and avoidable risks. | ||
|
|
||
| Existing transaction types in Ethereum only define their inputs, while the behavior and the outcome of | ||
| transactions is only defined by the code permanently deployed on-chain. | ||
| With the growing complexity of the deployed codebases and the growing monetary value controlled by this code, | ||
| such an approach becomes increasingly more dangerous. | ||
|
|
||
| By providing the Wallets and dApps with the ability to restrict the possible **outcomes** of a transaction, | ||
| we can create a tool that users and wallets will apply to reduce their risk levels. | ||
| we create a tool that users and wallets will apply to reduce their risk levels. | ||
|
|
||
| ## Specification | ||
|
|
||
| ### Constants | ||
|
|
||
| | Name | Value | | ||
| |------------|-------| | ||
| | RESTRICTED_TX_COST | TBD | | ||
| |TRACE_CALL_GAS_COST|TBD| | ||
| |GET_TRACE_CALL_ADDRESS|TBD| | ||
| |RESTRICTED_EXECUTION_TX_TYPE|TBD| | ||
|
|
||
| ### New Transaction Type | ||
|
|
||
| We introduce a new [EIP-2718](./eip-2718.md) transaction, "restricted execution transaction", where the `TransactionType` is `RESTRICTED_EXECUTION_TX_TYPE` 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, execution_restrictions, signature_y_parity, signature_r, signature_s]) | ||
| rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, value, calldata, access_list, authorization_list, asserter_address, asserter_data, signature_y_parity, signature_r, signature_s]) | ||
forshtat marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| ### Execution Restrictions | ||
| * `asserter_address` - the address of an existing contract that will be called for the [Assertion Frame](#assertion_frame). | ||
|
Check failure on line 55 in EIPS/eip-7906.md
|
||
| * `asserter_data` - the data to be passed as a call data to the Assertion Frame. In case the `asserter_address` is not set, this field acts as a [One-Time Restrictions Code](#one_time_restrictions_code). | ||
|
Check failure on line 56 in EIPS/eip-7906.md
|
||
forshtat marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ### One-Time Restrictions Code | ||
|
|
||
| The `asserter_address` and `asserter_data` field behave similarly to the `destination` and `calldata` fields in existing transaction types. | ||
forshtat marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| If the `asserter_address` value is not set, the `asserter_data` is loaded and executed similarly to the `init_code`. | ||
|
||
|
|
||
| This code is executed in a static context and cannot modify the blockchain state, set contract code or deploy new contracts. | ||
|
|
||
| ### Assertion Frame | ||
|
|
||
| After the transaction execution frame is finished without reverting, the `RESTRICTED_EXECUTION_TX_TYPE` transactions MUST also successully execute a second execution frame. This frame runs in a static context and cannot modify storage or emit logs. | ||
|
|
||
| The purpose of this frame is to execute the state change assertions as prescribed by the `asserter_address` and `asserter_data` parameters. | ||
|
|
||
| In case of a revert in the Assertion Frame, the entire transaction is reverted. | ||
|
|
||
| The gas costs in the Assertion Frame are charged same as in the regular execution. | ||
|
|
||
| ### Execution Restrictions Assertion Frame | ||
|
|
||
| There are a number of parameters that constitute the core of the transaction's execution restriction. | ||
| These parameters are joined together and RLP encoded as part of the transaction payload. | ||
|
|
@@ -61,209 +83,120 @@ | |
|
|
||
| The transaction is considered to be a valid transaction that can be included in a block and pays its own gas regardless of the contents of the `execution_restrictions` parameter. | ||
|
|
||
| #### Storage Altering Operations | ||
| ### Transaction Trace Precompile | ||
|
|
||
| The term "permitted operation" is defined as follows: | ||
| We introduce a precompile at address `GET_TRACE_CALL_ADDRESS`. | ||
|
|
||
| * `READ` - read-only access to the given slot | ||
| * `DECREASE` - read and decrease a value in the given slot | ||
| * `INCREASE` - read and increase a value in the given slot | ||
| * `DELTA` - read and either `INCREASE` or `DECREASE` a value in the given slot | ||
| * `WRITE` - any storage read or write operation in the given slot | ||
| * `TRANSIENT_WRITE` - any storage read or write operation in the given slot is allowed **during** the execution, but must remain unchanged as a result of the transaction | ||
| When called in a regular execution frame, the call returns a full stack trace of the current frame up to this point. | ||
|
|
||
| For the `DELTA`, `INCREASE`, and `DECREASE` the value stored in the slot MUST be treated as an unsigned integer value. | ||
| When called in the Assertion Frame, the call returns a full stack trace of the entire transaction. | ||
|
|
||
| #### Explicitly Permitted Operations | ||
| The format of the returned transaction stack trace is described in [Transaction Trace Data Structure](#). | ||
|
|
||
| By default `RESTRICTED_EXECUTION_TX_TYPE` transactions are not permitted to perform the following operations: | ||
| ### Transaction Trace Data Structure | ||
|
|
||
| 1. Modifying any account's `balance` | ||
| 2. Modifying any account's storage slots | ||
| 3. Executing any of the [Opcodes Restricted by Default](#opcodes-restricted-by-default) | ||
| The stack trace is represented as an ABI encoding of the following struct: | ||
|
|
||
| The `permitted_operations` field provides a description of what operations are permitted as part of the transaction's execution. | ||
| The operations described by this field are permitted for the specified addresses. | ||
| ```solidity | ||
| struct Trace { | ||
| Call[] calls; | ||
| } | ||
| ##### Wildcard Permitted Operation | ||
| struct Call { | ||
| address sender; | ||
| address target; | ||
| Storage[] storage; | ||
| Balance[] balances; | ||
| CodeHash[] codeHash; | ||
| OpCode[] opCodes; | ||
| Call[] calls; | ||
| } | ||
| Providing the special value `[0x0000000000000000000000000000000000000000, [], []]` indicates that all | ||
| operations are permitted for all addresses not explicitly mentioned in either the [Explicitly Permitted Operations](#explicitly-permitted-operations) or [Explicitly Banned Operations](#explicitly-banned-operations) lists. | ||
| struct Storage { | ||
| bytes32 slotId; | ||
| bytes32 oldValue; | ||
| bytes32 newValue; | ||
| } | ||
| #### Explicitly Banned Operations | ||
| struct Balance { | ||
| address account; | ||
| uint256 oldBalance; | ||
| uint256 newBalance; | ||
| } | ||
| The term "banned operation" is defined as follows: | ||
| struct CodeHash { | ||
| address contract; | ||
| bytes32 newCodeHash; | ||
| } | ||
| * `ANY` - **any** read and write access to the given slot | ||
| * `DECREASE` - decrease of a value in the given slot | ||
| * `INCREASE` - increase of a value in the given slot | ||
| * `WRITE` - write access to the given slot | ||
|
|
||
| Unlike the `permitted_operations`, all `INCREASE` and `DECREASE` operations are banned regardless of the amount the value changes. | ||
| There is no `DELTA` operation defined for the banned operations. | ||
|
|
||
| In case there is a conflict between a permit list and a ban list, the **ban list takes precedence**, and the transaction MUST **revert** upon violation. | ||
| struct OpCode { | ||
| uint8 opCode; | ||
| bytes32[] params; | ||
| } | ||
| ``` | ||
|
|
||
| #### Opcodes Restricted by Default | ||
| #### Opcodes Traced | ||
|
|
||
| The following opcodes have non-local effects and their applications are restricted by `RESTRICTED_EXECUTION_TX_TYPE` by default: | ||
| Including all opcodes called during a transaction execution in the stack trace is not practical. | ||
| Instead, only the following opcodes with potentially dangerous non-local effects are reported as part of the `opCodes` field: | ||
|
|
||
| * `SELFDESTRUCT` (`0xFF`) | ||
| * `DELEGATECALL` (`0xF4`) | ||
| * `CALLCODE` (`0xF2`) | ||
| * `STATICCALL` (`0xFA`) | ||
| * `CALL` (`0xFA`) | ||
| * `CREATE` (`0xF0`) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe these should still be traced?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Contract creation will be traced in a separate field, as the inputs to "create" opcodes are not very informative. |
||
| * `CREATE2` (`0xF5`) | ||
| * `LOG` (`0xA0`) | ||
| * `LOG1` (`0xA1`) | ||
| * `LOG2` (`0xA2`) | ||
| * `LOG3` (`0xA3`) | ||
| * `LOG4` (`0xA4`) | ||
| * `REVERT` (`0xFD`) | ||
| * `INVALID` (`0xFE`) | ||
| * `KECCAK256` (`0x20`) | ||
|
|
||
| Additionally, we introduce special values for non-opcode-based restrictions: | ||
|
|
||
| * All opcodes (`0xffff`) - used to explicitly permit or ban all opcodes for an address | ||
| * `CALL` with value (`0xff00`) - used to explicitly permit or ban calls only if they carry a value in native currency | ||
| * Current contract deployment (`0xff01`) - preventing the specified address from having a code inserted in its place | ||
| * Reverted call (`0xff02`) - preventing the specified address from executing any reverted call | ||
|
|
||
| Consequently, all EIPs defining new opcodes MUST specify whether the opcode should be restricted by default or not. | ||
|
|
||
| ### New opcode `TXRESTRICTHASH` | ||
|
|
||
| The new `TXRESTRICTHASH` opcode pushes the following value onto the stack: | ||
|
|
||
| ``` | ||
| keccak256(execution_restrictions) | ||
| ``` | ||
|
|
||
| ### Revert Reason | ||
|
|
||
| When executed in a view mode, a `RESTRICTED_EXECUTION_TX_TYPE` transaction with an `execution_restrictions` violation MUST return with the following revert reason: | ||
|
|
||
| ``` | ||
| error ExecutionRestrictionViolation(address _address, bytes32 _slot, bytes32 _opcode); | ||
| ``` | ||
|
|
||
| Where: | ||
|
|
||
| * `_address` - the violating contract's address | ||
| * `_slot` - the storage slot that has caused a violation, or `0x0` if not slot-related | ||
| * `_opcode` - the exact opcode that has caused the rule violation | ||
|
|
||
| ### RLP-encoding of the "Execution Restrictions" Parameter | ||
|
|
||
| The value of the `execution_restrictions` parameter is expressed as a two-element `[permitted_operations, banned_operations]` RLP tuple. | ||
|
|
||
| #### Permitted Operations | ||
|
|
||
| We define the following constants to express various [permitted operations](#storage-altering-operations): | ||
|
|
||
| * `0x00` - permit `READ` operation | ||
| * `0x01` - permit `DECREASE` operation | ||
| * `0x02` - permit `INCREASE` operation | ||
| * `0x03` - permit `DELTA` operation | ||
| * `0x04` - permit `WRITE` operation | ||
|
|
||
| The `DELTA`, `INCREASE`, and `DECREASE` operations are expressed as a two-element `[operation, value]` RLP tuple. | ||
|
|
||
| The `permitted_operations` parameter is represented by an array of the following internal structure: | ||
|
|
||
| 1. Address of an account with explicitly permitted operations. | ||
| 2. Account balance permitted operation type, expressed as `[operation, value]` RLP tuple. | ||
| 3. An array of permitted operations per storage slot. | ||
| If left empty, all slots are permitted for arbitrary read and write. | ||
| If the same slot ID appears multiple types, each operation is permitted for the given slot. | ||
| * Storage Slot Identifier | ||
| * Permitted "operation" | ||
| * Maximum permitted amount (optional) | ||
| 4. An array of explicitly permitted [Restricted Opcodes](#opcodes-restricted-by-default). | ||
|
|
||
| Example of a `permitted_operations` encoding: | ||
|
|
||
| ``` | ||
| rlp( | ||
| [ | ||
| [0xAddress1, [0x01, 0xde0b6b3a7640000], [[0xSlotID1, [0x00]], [0xSlotID2, [0x01]], ["0xF4", "0xF5"]]], | ||
| [0xAddress2, [0x02, de0b6b3a7640000], [0xSlotID, [0x02, 0x777]]], | ||
| [0xAddress3, [], [0xSlotID, [0x00]]], | ||
| ] | ||
| ) | ||
| ``` | ||
| ## Rationale | ||
|
|
||
| #### Banned Operations | ||
| ### New Transaction Type and Assertion Frame | ||
|
|
||
| * `0x00` - ban `ANY` operation | ||
| * `0x01` - ban `DECREASE` operation | ||
| * `0x02` - ban `INCREASE` operation | ||
| * `0x04` - ban `WRITE` operation | ||
| One of the main advantages of a new Transaction Type for the Restricted Behaviour feature is the ability to protect all existing EOAs, and not just smart accounts. This makes it preferable to introduce a new Transaction Type instead of any other approach that would only work for smart contract accounts. | ||
|
|
||
| The `banned_operations` parameter is represented by an array of the following internal structure: | ||
| ### Transaction Trace Precompile Behaviour | ||
|
|
||
| 1. Address of an account with explicitly banned operations | ||
| 2. Account balance banned operation type, expressed as `operation` value. | ||
| 3. An array of banned operations per storage slot. If left empty, all slots are banned for `ANY` operation. | ||
| * Storage Slot Identifier | ||
| * Banned "operation" | ||
| 4. An array of explicitly banned opcodes. May contain any valid opcode value. | ||
| It is important for us to provide the same protection level to both EOAs and Smart Accounts. The Smart Accounts are not able to initiate a `RESTRICTED_EXECUTION_TX_TYPE` transaction themselves, and instead need to rely on checks performed during the regular execution frame of any transaction type. | ||
|
|
||
| Example of a `banned_operations` encoding: | ||
| By exposing the `GET_TRACE_CALL_ADDRESS` precompile at all times, we allow any smart contract to perform the state change assertions it may need to ensure safety and security. | ||
|
|
||
| ``` | ||
| rlp( | ||
| [ | ||
| [0xAddress1, 0x01, [[0xSlotID1, 0x00], [0xSlotID2, 0x01], ["0xF4", "0xF5"]]], | ||
| [0xAddress2, 0x04, [0xSlotID, 0x02]], []], | ||
| ] | ||
| ) | ||
| ``` | ||
|
|
||
| ## Rationale | ||
| ### Deployable and One-Time Restrictions Code | ||
|
|
||
| ### Explicitly Banned Operations Rationale | ||
| In some scenarios, the wallets are likely to want to apply the exact same transaction behavour to all transactions they initiate. | ||
forshtat marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| In general, providing this value should be less preferable compared to making transactions with only a list of explicitly permitted operations and an outright ban on any other access. | ||
| In this case, it is reasonalbe and more efficient to deploy the assertions on-chain as a smart contract module, and provide its address and the inputs it may need. | ||
|
|
||
| This, however, is not practical with the current diversity of pre-existing smart contracts. | ||
| The transaction's execution path may depend on any number of external factors and the inconvenience of using sporadically reverting `RESTRICTED_EXECUTION_TX_TYPE` would outweigh the security benefits. | ||
|
|
||
| The task of preparing the Execution Restrictions largely belongs to the dApp itself. | ||
|
|
||
| ### New `TXRESTRICTHASH` opcode | ||
|
|
||
| With the growing adoption of Account Abstraction, it is important to expose the `execution_restrictions` value to the Smart Contract Wallets. | ||
| However, it is possible that the wallet may want to prepare the restrictions for the transaction dynamically. In that case, there is no benefit in having the assertion code permanently deployed, and it is more efficient to provide such code as part of the transaction payload. Luckily, the EVM already has a very similar behaviour defined for the `init_code` field, and it appears to fit the task perfectly. | ||
|
|
||
| ## Backwards Compatibility | ||
|
|
||
| This proposal describes a new transaction type that should not affect the functionality of existing systems. | ||
|
|
||
| However, providing strict Execution Restrictions for transactions using smart contracts with multiple possible branching execution paths will result in unpredictable reverts. | ||
|
|
||
| This proposal does intentionally attempt to create pressure on smart contract developers to create well-structured, linear execution flows for their users. | ||
|
|
||
| ## Security Considerations | ||
|
|
||
| ### Correct Wallet UI presentation | ||
|
|
||
| The success of the `RESTRICTED_EXECUTION_TX_TYPE` transaction initiative lies in the wallet's ability to correctly | ||
| understand and present the restrictions they are imposing on the transaction to the users. | ||
| Successfull use of the `RESTRICTED_EXECUTION_TX_TYPE` transaction type requires the wallets to be abile to correctly | ||
| understand and present the restrictions imposed on the transaction to the users. | ||
|
|
||
| Wallets will need to be able to understand the meaning of the slots and operations being permitted by the transaction. | ||
| Wallets will need to be able to understand the meaning of the state changes being permitted by the transaction. | ||
| This requires wallets to be aware of all major ERC standards, such as [ERC-20](./eip-20.md) and [ERC-721](./eip-721.md). | ||
| In many cases, this also requires the wallets to be able to fetch and analyze the source code of the executed contracts. | ||
|
|
||
| However, the introduction of the `execution_restrictions` parameter to transactions significantly streamlines the process by removing the need for a deep understanding of the executed code. | ||
| Instead, only high-level information about the storage slots' meaning is required for a clear and safe representation of possible transaction outcomes. | ||
|
|
||
| Note that for transactions involving operations that the wallet is not able to fully "understand", the user will still be asked to sign on an opaque set of changes. | ||
| This is still an improvement from the "blind signing" of today by allowing an explicit ban on accessing certain balances or opcodes. | ||
| However, the introduction of the Execution Restrictions feature significantly streamlines the process by removing the need for a deep understanding of the executed **code**. | ||
| Instead, only high-level information about the stack traces' meaning is required for a clear and safe representation of possible transaction outcomes. | ||
|
|
||
| ### Insufficiently Restrictive Transactions | ||
|
|
||
| The worst outcome of introducing a security feature is creating a false sense of security for its user. | ||
|
|
||
| Wallets are expected to provide the banned operations list in a way that protects their users' valuable assets. | ||
| Wallets are expected to provide the behaviour restriction logic that protects their users' valuable assets. | ||
|
|
||
| It is critical that dApps, wallets, and users become educated about the consequences of not limiting their transactions' execution with sufficient strictness. | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.