EIP-3074: Sponsored Transaction Precompile Source

AuthorSam Wilson
Discussions-Tohttps://ethereum-magicians.org/t/eip-3074-sponsored-transaction-precompile/4880
StatusDraft
TypeStandards Track
CategoryCore
Created2020-10-15

Simple Summary

Creates a new precompile, analogous to CALL (0xF1), that sets CALLER (0x33) based on an ECDSA signature.

Abstract

This EIP creates two precompiles:

  • CALL_PRECOMPILE - forwards a CALL, setting CALLER according to an ECDSA signature, using a invoker-sponsee nonce for replay protection.
  • NONCE_PRECOMPILE - provides access to invoker-sponsee nonces expected by CALL_PRECOMPILE.

Motivation

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), these solutions require specific support in callee contracts.

Specification

Sponsored transactions are implemented with the addition of two precompiles:

  • The first, at address 0x13, which functions like a CALL instruction that additionally sets the caller address based on an ECDSA signature.
  • The second, at address 0x14, provides access to the current nonce for the given invoker-sponsee pair.

Definitions

  • 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 invoker-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 invoker.
  • Sponsee - the account which signed the transactions-like package.
  • Invoker - 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.

API

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 invoker 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-155.

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, invoker, chainid]))).

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 invoker’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

NONCE_PRECOMPILE requires the following two arguments:

  • invoker - the invoker 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.

Nonces

The two precompiles will maintain a nonce for each pair of invoker address and sponsee address, in essence:

{
    (0x1234...5678, 0xEEEE...EEEE) => 55,
    (0x1122...3344, 0xBBBB...BBBB) => 89,
}

Where:

  • 0x1234...5678 and 0x1122...3344 are the invoker 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

CALL_PRECOMPILE

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

NONCE_PRECOMPILE

TODO: Probably something like the sum of:

  • An SLOAD to read the current nonce

Rationale

Another Sponsored Transaction EIP

Other approaches to sponsored transactions, which rely on introducing a new transaction type, are not immediately compatible with 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 CALLER. 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 invokers and sponsors without sacrificing security or user experience for sponsees.

Nonces

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 invoker nonce: every sponsored transaction from the invoker’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 invoker-sponsee pair, we get some attractive properties:

  • A transaction package can only be invalidated if both the invoker and sponsee cooperate, which is nice for EOA sponsors, and necessary for AA contracts.
  • The SELFDESTRUCT operation doesn’t introduce replay attacks.

Precompile vs. Opcode

Opcodes do not have externally visible addresses, and therefore cannot be called directly by an EOA. Using a precompile allows a sponsor to avoid an intermediary contract call should they want to use this functionality directly.

Backwards Compatibility

No known issues.

Test Cases

TODO

Implementation

TODO

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.

Citation

Please cite this document as:

Sam Wilson, "EIP-3074: Sponsored Transaction Precompile [DRAFT]," Ethereum Improvement Proposals, no. 3074, October 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-3074.