mirror of
https://github.com/status-im/EIPs.git
synced 2025-02-23 04:08:09 +00:00
Automatically merged updates to draft EIP(s) 3074 (#3354)
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
080ac64e06
commit
0071020b8d
@ -1,7 +1,7 @@
|
||||
---
|
||||
eip: 3074
|
||||
title: Native Sponsored Transactions
|
||||
author: Sam Wilson (@SamWilsn)
|
||||
author: Sam Wilson (@SamWilsn), Ansgar Dietrichs (@adietrichs), Matt Garnett (@lightclient)
|
||||
discussions-to: https://ethereum-magicians.org/t/eip-3074-sponsored-transaction-precompile/4880
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
@ -74,29 +74,26 @@ In a static context (such as the one created by `STATICCALL`), `CALLFROM` with a
|
||||
| `top - 1` | `r` |
|
||||
| `top - 2` | `s` |
|
||||
| `top - 3` | `sponsee` |
|
||||
| `top - 4` | `depthLeft` |
|
||||
| `top - 5` | `extra` |
|
||||
| `top - 6` | `gas` |
|
||||
| `top - 7` | `callee` |
|
||||
| `top - 8` | `value` |
|
||||
| `top - 9` | `argsOffset` |
|
||||
| `top - 10` | `argsLength` |
|
||||
| `top - 11` | `retOffset` |
|
||||
| `top - 12` | `retLength` |
|
||||
| `top - 4` | `extra` |
|
||||
| `top - 5` | `gas` |
|
||||
| `top - 6` | `callee` |
|
||||
| `top - 7` | `value` |
|
||||
| `top - 8` | `argsOffset` |
|
||||
| `top - 9` | `argsLength` |
|
||||
| `top - 10` | `retOffset` |
|
||||
| `top - 11` | `retLength` |
|
||||
|
||||
The signature (`yParity`, `r`, `s`) arguments must be computed from `secp256k1(keccak256(type || abi.encode(invoker, chainid, extra)))`.
|
||||
The signature (`yParity`, `r`, `s`) arguments must be computed from `secp256k1(keccak256(type || abi.encode(invoker, extra)))`.
|
||||
|
||||
The arguments are defined to be:
|
||||
|
||||
- `type: uint8` - [EIP-2718](./eip-2718.md) transaction type (always `SPONSORED_TYPE`);
|
||||
- `invoker: address` - the address of the invoker contract;
|
||||
- `chainid: uint256` - the chain id, as returned by the `CHAINID` (`0x46`) opcode;
|
||||
- `extra: uint256` - extra data, which can be used in the invoker to implement replay protection;
|
||||
- `callee: address` - address of the callee;
|
||||
- `gas: uint256` - exact gas limit which must be provided with the call into `CALLFROM`;
|
||||
- `value: uint256` - exact amount of Ether in wei to be received by the callee;
|
||||
- `sponsee: address` - address of the sponsee;
|
||||
- `depthLeft: uint256` - minimum call depth available to the callee;
|
||||
- `argsOffset: uint256`, `argsLength: uint256` - region of memory used as the calldata for the call into the callee;
|
||||
- `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.
|
||||
@ -117,7 +114,6 @@ The arguments are defined to be:
|
||||
- Invalid signature
|
||||
- The address recovered from `yParity`, `r`, and `s` does not match `sponsee`
|
||||
- The balance of the invoker is less than `value`
|
||||
- There is insufficient available call depth for the callee to make `depthLeft` nested calls
|
||||
|
||||
`valid` must be a one in all other cases.
|
||||
|
||||
@ -155,7 +151,7 @@ Where `cost_of_call(...)` is the cost of a `CALL` (`0xF1`) instruction with the
|
||||
|
||||
### Omitting Arguments
|
||||
|
||||
The signature arguments `chainid` and `invoker` are not included in arguments to the instruction because they can be calculated by the instruction itself.
|
||||
The `invoker` signature argument is not included in the arguments to the instruction because it can be calculated by the instruction itself.
|
||||
|
||||
### Two Return Values
|
||||
|
||||
@ -189,14 +185,18 @@ More logic can be implemented around the `CALLFROM` instruction, giving more con
|
||||
|
||||
Earlier approaches to this problem included mechanisms for replay protection, and also signed over value, gas, and other arguments to `CALLFROM`. Instead, this proposal explicitly delegates these responsibilities to the invoker contract.
|
||||
|
||||
As originally written, this proposal specified a precompile with storage to track nonces. Since a precompile with storage is unprecedented, a later revision moved replay protection into the invoker contract, necessitating a certain level of user trust in the invoker, while also opening the door to more creative replay protection schemes in the future. Building on this idea of trusted invokers, the other signed fields in the transaction-like package were eliminated until only `invoker`, `chainid`, and `extra` remained.
|
||||
As originally written, this proposal specified a precompile with storage to track nonces. Since a precompile with storage is unprecedented, a later revision moved replay protection into the invoker contract, necessitating a certain level of user trust in the invoker, while also opening the door to more creative replay protection schemes in the future. Building on this idea of trusted invokers, the other signed fields in the transaction-like package were eliminated until only `invoker` and `extra` remained.
|
||||
|
||||
The motivation for including `invoker` is to bind a particular transaction-like package to a single invoker. If `invoker` was not part of the TLP, a malicious invoker could reuse the TLP to impersonate the EOA.
|
||||
|
||||
While `chainid` is not strictly necessary, and could be enforced in the invoker contract, it's reasonable to assume every well-behaved invoker will check the chain id. Without `chainid`, a TLP would be valid on multiple chains.
|
||||
|
||||
Finally, `extra` should be used by invoker contracts to implement replay protection and security around calldata, value, and other parameters. For example, an invoker may assume `extra` to be `keccak256(abi.encode(gas, value, nonce))`, guaranteeing that the sponsee intended to set those parameters to those specific values. Without `extra`, invokers would not be able to determine if other values (eg. `gas`, `value`, calldata, etc.) had been tampered with.
|
||||
|
||||
### On Call Depth
|
||||
|
||||
The EVM limits the maximum number of nested calls, and naively allowing a sponsor to manipulate the call depth before reaching the invoker would introduce a griefing attack against the sponsee. That said, with the 63/64th gas rule, and the cost of `CALLFROM`, the stack is effectively limited to a much smaller depth than the hard maximum by the `gas` parameter.
|
||||
|
||||
It is, therefore, sufficient for the invoker to guarantee a minimum amount of gas, because there is no way to reach the hard maximum call depth with any reasonable (i.e. less than billions) amount of gas.
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
No known issues.
|
||||
@ -226,7 +226,7 @@ The following is a non-exhaustive list of checks/pitfalls/conditions that invoke
|
||||
- Replay protection should be implemented by the invoker, and included in `extra`. Without it, a malicious sponsor can replay a TLP, repeating its effects.
|
||||
- `value` should be included in `extra`. Without it, a malicious sponsor could cause unexpected effects in the callee.
|
||||
- `gas` should be included in `extra`. Without it, a malicious sponsor could cause the callee to run out of gas and fail, griefing the sponsee.
|
||||
- `depthLeft` should be included in `extra`. Without it, a malicious sponsor may arbitrarily manipulate the call depth to cause the callee to fail, griefing the sponsee.
|
||||
- The current chain id should be included in `extra` and checked on every transaction. Without it, a malicious sponsor could replay a TLP on a different chain.
|
||||
- `callee` and `calldata` should be included in `extra`. Without them, a malicious sponsor may call arbitrary functions in arbitrary contracts.
|
||||
|
||||
A poorly implemented invoker can _allow a malicious sponsor to take near complete control over a sponsee's EOA_.
|
||||
|
Loading…
x
Reference in New Issue
Block a user