mirror of
https://github.com/status-im/EIPs.git
synced 2025-02-23 12:18:16 +00:00
Automatically merged updates to draft EIP(s) 3074 (#3344)
Hi, I'm a bot! This change was automatically merged because: - It only modifies existing Draft, Review, or Last Call EIP(s) - The PR was approved or written by at least one author of each modified EIP - The build is passing
This commit is contained in:
parent
5cc63c52e7
commit
fbae2549c7
122
EIPS/eip-3074.md
122
EIPS/eip-3074.md
@ -15,7 +15,7 @@ Creates a new EVM instruction, analogous to `CALL` (`0xF1`), that sets `CALLER`
|
||||
|
||||
## Abstract
|
||||
|
||||
This EIP creates an EVM instruction (`TXCALL`) which forwards a `CALL`, setting `CALLER` according to an ECDSA signature.
|
||||
This EIP creates an EVM instruction (`NAMETBD`) which forwards a `CALL`, setting `CALLER` according to an ECDSA signature.
|
||||
|
||||
## Motivation
|
||||
|
||||
@ -27,19 +27,34 @@ While it is possible to emulate sponsored transactions (ex. [Gas Station Network
|
||||
|
||||
## Specification
|
||||
|
||||
An opcode, at `0xf9`, functions like a `CALL` instruction that additionally:
|
||||
An opcode, at `0xf9`, shall function like a `CALL` (`0xF1`) instruction:
|
||||
- To the `to` address,
|
||||
- Transferring `value` wei from the invoker to the callee,
|
||||
- Passing `gas` gas for execution,
|
||||
- With calldata in the memory region specified by `argsOffset` and `argsLength`,
|
||||
- With a return data region specified by `retOffset` and `retLength`.
|
||||
|
||||
- sets the caller addresses based on an ECDSA signature, and
|
||||
- optionally transfers Ether from the recovered account.
|
||||
Additionally, the opcode shall:
|
||||
|
||||
- Set the caller address based on an ECDSA signature.
|
||||
|
||||
`NAMETBD` shall increase the call depth by one, in the same way as `CALL`. `NAMETBD` shall not increase the call depth by two (as it would if it first called into the sponsee account and then into the callee.)
|
||||
|
||||
In a static context (such as the one created by `STATICCALL`), `NAMETBD` with a non-zero `value` shall exit the current execution frame immediately (in the same way `CALL` behaves with a non-zero value in a static context.)
|
||||
|
||||
### Definitions
|
||||
|
||||
- **`TXCALL`** - the specific instruction encoded as `0xf9`, introduced by this EIP, which implements the `CALL` analogue.
|
||||
- **Transaction-like Package** - the signed arguments passed to `TXCALL`.
|
||||
- **`NAMETBD`** - the specific instruction encoded as `0xf9`, introduced by this EIP, which implements the `CALL` analogue.
|
||||
- **Transaction-like Package** - the signed arguments passed to `NAMETBD`.
|
||||
- **Sponsor** - the account which is responsible for paying gas fees and sending the transaction.
|
||||
- **Sponsee** - the account which signed the transaction-like package.
|
||||
- **Invoker** - the account or contract which contains `TXCALL`.
|
||||
- **Callee** - the target of the call from `TXCALL`.
|
||||
- **Invoker** - the account or contract which contains `NAMETBD`.
|
||||
- **Callee** - the target of the call from `NAMETBD`.
|
||||
|
||||
### Conventions
|
||||
|
||||
- **`top - N`** - the `N`th most recently pushed value on the EVM stack, where `top - 0` is the most recent.
|
||||
- **`||`** - byte concatenation operator.
|
||||
|
||||
### Constants
|
||||
|
||||
@ -51,58 +66,71 @@ An opcode, at `0xf9`, functions like a `CALL` instruction that additionally:
|
||||
|
||||
#### Inputs
|
||||
|
||||
`TXCALL` requires the following stack arguments:
|
||||
`NAMETBD` shall require the following stack arguments:
|
||||
|
||||
| `top - 0` | `top - 1` | `top - 2` | `top - 3` | `top - 4` | `top - 5` |
|
||||
| --------- | --------- | ------------ | ------------ | ----------- | ----------- |
|
||||
| `gas` | `value` | `argsOffset` | `argsLength` | `retOffset` | `retLength` |
|
||||
| Stack | Value |
|
||||
| ---------- | ------------ |
|
||||
| `top - 0` | `yParity` |
|
||||
| `top - 1` | `r` |
|
||||
| `top - 2` | `s` |
|
||||
| `top - 3` | `sponsee` |
|
||||
| `top - 4` | `type` |
|
||||
| `top - 5` | `nextra` |
|
||||
| `top - 6` | `gas` |
|
||||
| `top - 7` | `callee` |
|
||||
| `top - 8` | `value` |
|
||||
| `top - 9` | `argsOffset` |
|
||||
| `top - 10` | `argsLength` |
|
||||
| `top - 11` | `retOffset` |
|
||||
| `top - 12` | `retLength` |
|
||||
|
||||
The signature (`yParity`, `r`, `s`) arguments shall be computed from `secp256k1(keccak256(type || abi.encode(invoker, chainid, nextra, gas, callee, value, data)))`.
|
||||
|
||||
The arguments memory region shall be encoded as `type || abi.encode(v, r, s, sponsee, nextra, mingas, to, data)`.
|
||||
|
||||
The signature (`v`, `r`, `s`) arguments are computed from `secp256k1(keccak256(type || abi.encode(invoker, chainid, value, nextra, mingas, to, data)))`.
|
||||
|
||||
The arguments are:
|
||||
The arguments are defined to be:
|
||||
|
||||
- `type: uint8` - [EIP-2718](./eip-2718.md) transaction type (currently always `SPONSORED_TYPE`);
|
||||
- `sponsee: address` - address of the sponsee;
|
||||
- `invoker: address` - the address of the invoker contract;
|
||||
- `chainid: uint256` - the chain id, as returned by the `CHAINID` (`0x46`) opcode;
|
||||
- `nextra: uint256` - extra data, which can be used in the invoker to implement replay protection;
|
||||
- `to: address` - address of the callee;
|
||||
- `mingas: uint256` - minimum gas limit which must be provided with the call into `TXCALL`;
|
||||
- `callee: address` - address of the callee;
|
||||
- `gas: uint256` - exact gas limit which must be provided with the call into `NAMETBD`;
|
||||
- `value: uint256` - exact amount of Ether in wei to be received by the callee;
|
||||
- `data: bytes` - the calldata for the call into `to`; and
|
||||
- `v: uint8`, `r: bytes32`, `s: bytes32` - signature for the package, including chain id as specified in [EIP-155](./eip-155.md).
|
||||
- `data: bytes` - the calldata for the call into the callee;
|
||||
- `sponsee: address` - address of the sponsee;
|
||||
- `argsOffset: uint256`, `argsLength: uint256` - region of memory used as the calldata for the call into the callee, which should be equal to `data`;
|
||||
- `retOffset: uint256`, `retLength: uint256` - region of memory filled with the return data from the call into the callee; and
|
||||
- `yParity: uint8`, `r: bytes32`, `s: bytes32` - signature for the package.
|
||||
|
||||
#### Outputs
|
||||
|
||||
`TXCALL` pushes the following two values onto the stack:
|
||||
`NAMETBD` pushes the following two values onto the stack:
|
||||
|
||||
| `top - 0` | `top - 1` |
|
||||
| ------------- | ----------------- |
|
||||
| `success` | `calleeSuccess` |
|
||||
| Stack | Value |
|
||||
| ---------- | --------- |
|
||||
| `top - 0` | `valid` |
|
||||
| `top - 1` | `success` |
|
||||
|
||||
|
||||
##### `valid`
|
||||
|
||||
`valid` shall be zero in the following cases:
|
||||
- `type != SPONSORED_TYPE`
|
||||
- Invalid signature
|
||||
- The address recovered from `yParity`, `r`, and `s` does not match `sponsee`
|
||||
- Gas limit supplied with the call into `NAMETBD` is not equal to the signed `gas`
|
||||
- The transaction's remaining gas is less than the signed `gas`
|
||||
- The value sent with the call is not equal to the signed `value`
|
||||
|
||||
`valid` shall be a one in all other cases.
|
||||
|
||||
##### `success`
|
||||
|
||||
`success` shall be zero in the following cases:
|
||||
- `type != SPONSORED_TYPE`
|
||||
- Invalid signature
|
||||
- The address recovered from `v`, `r`, and `s` does not match `sponsee`
|
||||
- Gas limit supplied with the call into `TXCALL` is less than the signed `mingas`
|
||||
- The transaction's remaining gas is less than the signed `mingas`
|
||||
- The value sent with the call is not equal to the signed `value`
|
||||
- The current execution context is static (i.e. `STATICCALL`) and `value` is non-zero
|
||||
|
||||
`success` shall be a one in all other cases.
|
||||
|
||||
##### `calleeSuccess`
|
||||
|
||||
`calleeSuccess` shall be zero in the following cases:
|
||||
- `success == 0`
|
||||
- the code execution failed due to an exceptional halting or revert
|
||||
- call depth limit has been reached
|
||||
|
||||
`calleeSuccess` shall be a one in all other cases.
|
||||
`success` shall be a one in all other cases.
|
||||
|
||||
##### Return Data
|
||||
|
||||
@ -112,7 +140,7 @@ The return data area accessed with `RETURNDATASIZE` (`0x3d`) and `RETURNDATACOPY
|
||||
|
||||
### Gas Fees
|
||||
|
||||
The gas fees for `TXCALL` are calculated according to the following pseudo-code:
|
||||
The gas fees for `NAMETBD` are calculated according to the following pseudo-code:
|
||||
|
||||
```python
|
||||
S_cd = len(data) # In 256-bit words, rounded up
|
||||
@ -131,21 +159,21 @@ Where `len(data)` is the length of the region of memory defined by `argsOffset`
|
||||
|
||||
### Omitting Arguments
|
||||
|
||||
The signature arguments `value`, `chainid`, and `invoker` are not included in the memory region arguments to the instruction because they can be calculated by the instruction itself.
|
||||
The signature arguments `value`, `chainid`, and `invoker` are not included in arguments to the instruction because they can be calculated by the instruction itself.
|
||||
|
||||
### Two Return Values
|
||||
|
||||
It is important to differentiate between a failure in `TXCALL`'s preconditions versus a failure in the callee. Correctly implementing replay protection requires the invoker to change its state even if the callee fails (to burn the nonce) but doing so if, for example, the signature failed would be nonsensical. Several options exist for encoding these two failure cases: returning two stack elements, reserving a specific revert reason, or choosing different values in a single stack element.
|
||||
It is important to differentiate between a failure in `NAMETBD`'s preconditions versus a failure in the callee. Correctly implementing replay protection requires the invoker to change its state (i.e. burn the nonce) even if the callee fails; but doing so if, for example, the signature failed would be nonsensical. Several options exist for encoding these two failure cases: returning two stack elements, reserving a specific revert reason, or choosing different values in a single stack element.
|
||||
|
||||
First, it's important to note that all three options are a deviation from the semantics of other `CALL` opcodes, but this deviation is unavoidable.
|
||||
|
||||
Reserving a specific revert reason, for example `txcall failed`, is a large departure from other instructions. An invoker would need to inspect the revert reason to determine whether the callee reverted, or the `TXCALL` pre-conditions were invalidated, which implies reading and comparing memory values. Further, to remain sound when a callee reverts with `txcall failed`, `TXCALL` would need to replace the return data with some other value.
|
||||
Reserving a specific revert reason, for example `NAMETBD failed`, is a large departure from other instructions. An invoker would need to inspect the revert reason to determine whether the callee reverted, or the `NAMETBD` pre-conditions were invalidated, which implies reading and comparing memory values. Further, to remain sound if a callee were to revert with `NAMETBD failed`, `NAMETBD` would need to replace the return data with some other value.
|
||||
|
||||
Returning a single stack element with different values depending on the situation (ex. `0` on success, `1` when the pre-conditions are violated, and `2` when the callee reverts) introduces the opportunity for a subtle bug: it's trivially easy to misinterpret the return value (`CALL` returns non-zero on success), but it's much harder to ignore a whole new stack value.
|
||||
|
||||
### Sponsee in Arguments
|
||||
|
||||
Including `sponsee` in the arguments to `TXCALL` is a gas optimization. Without it, invokers would have to do their own `ecrecover` before calling into `TXCALL` to verify/adjust any state for replay protection.
|
||||
Including `sponsee` in the arguments to `NAMETBD` is a gas optimization for invoker contracts implementing some replay protection based on the sponsee address. Without the `sponsee` argument, invokers would have to do their own `ecrecover` before calling into `NAMETBD` to verify/adjust any state for replay protection.
|
||||
|
||||
### Reserving an [EIP-2718](./eip-2718.md) Transaction Type
|
||||
|
||||
@ -157,9 +185,9 @@ Other approaches to sponsored transactions, which rely on introducing a new tran
|
||||
|
||||
Besides better compatibility with AA, an instruction is a much less intrusive change than a new transaction type. This approach requires no changes in existing wallets, and little change in other tooling.
|
||||
|
||||
`TXCALL`'s single purpose is to set `CALLER`. It implements the minimal functionality to enable sender abstraction for sponsored transactions. This single mindedness makes `TXCALL` significantly more composable with existing Ethereum features.
|
||||
`NAMETBD`'s single purpose is to set `CALLER`. It implements the minimal functionality to enable sender abstraction for sponsored transactions. This single mindedness makes `NAMETBD` significantly more composable with existing Ethereum features.
|
||||
|
||||
More logic can be implemented around the call into `TXCALL`, giving more control to invokers and sponsors without sacrificing security or user experience for sponsees.
|
||||
More logic can be implemented around the `NAMETBD` instruction, giving more control to invokers and sponsors without sacrificing security or user experience for sponsees.
|
||||
|
||||
### Lack of Replay Protection
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user