title: Sponsored Transaction Precompile
author: Sam Wilson (@SamWilsn)
## Simple Summary
Creates a new precompile, analogous to `CALL`, that sets `msg.sender` based on an ECDSA signature.
We propose adding two precompiles:
- `CALL_PRECOMPILE` - forwards a `CALL`, setting `msg.sender` according to an ECDSA signature, using a relayer-sponsee nonce for replay protection.
- `NONCE_PRECOMPILE` - provides access to relayer-sponsee nonces expected by `CALL_PRECOMPILE`.
Sponsored transactions—the separation of fee payment from transaction content—have been a long standing feature request. Unlike similar proposals, this EIP specifies a method of implementing sponsored transactions that allows both externally owned accounts (EOAs) and [EIP-2938] contracts to act as sponsors.
With the explosion of tokens built on Ethereum, especially stable coins, it has become common for EOAs to hold valuable assets without holding any Ether at all. These assets must be converted to Ether before they can be used to pay gas fees, but without Ether to pay for the conversion, it's impossible to convert them. Sponsored transactions break the circular dependency.
While it is possible to emulate sponsored transactions (ex. [Gas Station Network][gsn]), these solutions require specific support in callee contracts.
We propose adding two precompiles to implement sponsored transactions:
- The first, at address `0x13`, would function like a `CALL` instruction that additionally sets the caller address based on an ECDSA signature.
- The second, at address `0x14`, would provide access to the current nonce for the given relayer-sponsee pair.
- **`CALL_PRECOMPILE`** - the specific precompile at address `0x13`, introduced by this EIP, which implements the `CALL` analogue.
- **`NONCE_PRECOMPILE`** - the specific precompile at address `0x14`, introduced by this EIP, which exposes relayer-sponsee nonces.
- **Transaction-like Package** - the signed arguments passed to `CALL_PRECOMPILE`.
- **Sponsor** - the account which is responsible for paying gas fees and sending the transaction. May or may not be the same as the relayer.
- **Sponsee** - the account which signed the transactions-like package.
- **Relayer** - the account or contract which directly calls into `CALL_PRECOMPILE`. May or may not be the same as the sponsor.
- **Callee** - the target of the call from `CALL_PRECOMPILE`.
`CALL_PRECOMPILE` requires the following eight arguments:
- `nonce` - the next nonce value, as described below;
- `to` - the address of the callee (not `CALL_PRECOMPILE`);
- `gaslimit` - the minimum gas limit which must be provided with the call into `CALL_PRECOMPILE`;
- `value` - the exact amount of Ether in wei to transfer from the relayer to the callee;
- `data` - the calldata for the call into `to`; and
- `v`, `r`, `s` - signature for the package, including chain id as specified in [EIP-115].
The arguments to `CALL_PRECOMPILE` are encoded as `rlp([nonce, gaslimit, to, value, data, v, r, s])`.
The signature (`v`, `r`, `s`) arguments are computed from `secp256k1(keccak256(rlp([nonce, gaslimit, to, value, data, relayer])))`.
`CALL_PRECOMPILE` returns a failure without changing the nonce in the following situations:
- Invalid signature
- Future or past nonce
- Gas limit supplied with the call into `CALL_PRECOMPILE` is less than the signed `gaslimit`
- The relayer's balance is insufficient to pay for the supplied gas plus `value`
`CALL_PRECOMPILE` returns a success in all other cases.
The return data of `CALL_PRECOMPILE` will be a single byte to indicate the status of the call into callee followed immediately by the return data from that call.
`NONCE_PRECOMPILE` requires the following two arguments:
- `relayer` - the relayer address; and
- `sponsee` - the sponsee address.
Assuming the calldata is the correct length, `NONCE_PRECOMPILE` will return a success, and place the nonce associated with the address pair in the return data.
The two precompiles will maintain a nonce for each pair of relayer address and sponsee address, in essence:
(0x1234...5678, 0xEEEE...EEEE) => 55,
(0x1122...3344, 0xBBBB...BBBB) => 89,
* `0x1234...5678` and `0x1122...3344` are the relayer addresses;
* `0xEEEE...EEEE` and `0xBBBB...BBBB` are the sponsee addresses; and
* `55` and `89` are the current nonce values for their respective pairs.
The nonce shall be incremented whenever a correctly signed transaction-like package containing the next nonce is submitted to `CALL_PRECOMPILE` with a sufficient gas limit.
### Gas Fees
TODO: Probably something like the sum of:
* The cost of a normal call, including calldata and signature size, etc.
* An `SLOAD` to read the current nonce
* An `SSTORE` to write the updated nonce
* Cost of an ecrecover
TODO: Probably something like the sum of:
* An `SLOAD` to read the current nonce
The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.
### Another Sponsored Transaction EIP
Other approaches to sponsored transactions, like [EIP-2711] and [EIP-2733], are incompatible with [EIP-2938] flavored account abstraction (AA). These proposals require a _signed_ transaction from the sponsor's account, which is not possible from an AA contract, because it has no private key to sign with.
Besides better compatibility with AA, a precompile 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.
`CALL_PRECOMPILE`'s single purpose is to set `msg.sender`. It implements the minimal functionality to enable sender abstraction for sponsored transactions. This single mindedness makes `CALL_PRECOMPILE` significantly more composable with existing Ethereum features.
More logic can be implemented around the call into `CALL_PRECOMPILE`, giving more control to relayers and sponsors without sacrificing security or user experience for sponsees.
Other nonce schemes either do not provide enough security, or are too inefficient/inconvenient to be practical.
- Use sponsor nonce: every transaction from the sponsor's account invalidates every transaction-like package.
- Use relayer nonce: every sponsored transaction from the relayer's account invalidates every other transaction-like package. Also interacts with `SELFDESTRUCT`.
- Use sponsee nonce: the sponsee could attack the sponsor by submitting another transaction with a conflicting nonce at a higher gas price.
Instead, by creating an independent nonce per relayer-sponsee pair, we get some attractive properties:
- A transaction package can only be invalidated if both the relayer and sponsee cooperate, which is nice for EOA sponsors, and necessary for AA contracts.
- The `SELFDESTRUCT` operation doesn't introduce replay attacks.
## Backwards Compatibility
No known issues.
## Test Cases
The implementations must be completed before any EIP is given status "Final", but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details.
## Security Considerations
- First precompiles that require persistent storage.
- Potential impersonation attacks if there is a bug in the signature verification.
- Potential replay-attack problems if there is a bug in the replay protection, or if two chains share chain ids.
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
Largely inspired by [EIP ? - CallWithSigner as a potential fix for the msg.sender problem][EIP-?] and [EIP-2711].