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
8.5 KiB
eip | title | author | discussions-to | status | type | category | created |
---|---|---|---|---|---|---|---|
3074 | Native Sponsored Transactions | Sam Wilson (@SamWilsn) | https://ethereum-magicians.org/t/eip-3074-sponsored-transaction-precompile/4880 | Draft | Standards Track | Core | 2020-10-15 |
Simple Summary
Creates a new EVM instruction, analogous to CALL
(0xF1
), that sets CALLER
(0x33
) based on an ECDSA signature.
Abstract
This EIP creates an EVM instruction (TXCALL
) which forwards a CALL
, setting CALLER
according to an ECDSA signature.
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
An opcode, at 0xf9
, functions like a CALL
instruction that additionally:
- sets the caller and origin addresses based on an ECDSA signature, and
- optionally transfers Ether from the recovered account.
Definitions
TXCALL
- the specific instruction encoded as0xf9
, introduced by this EIP, which implements theCALL
analogue.- Transaction-like Package - the signed arguments passed to
TXCALL
. - 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
.
Constants
Constant | Value | Description |
---|---|---|
SPONSORED_TYPE |
0x03 |
EIP-2718 transaction type reserved for transaction-like packages. |
API
Inputs
TXCALL
requires the following stack arguments:
top - 0 |
top - 1 |
top - 2 |
top - 3 |
top - 4 |
top - 5 |
---|---|---|---|---|---|
gas |
value |
argsOffset |
argsLength |
retOffset |
retLength |
The arguments memory region shall be encoded as type || abi.encode(v, r, s, sponsee, nextra, mingas, to, value, data)
, where:
type: uint8
- EIP-2718 transaction type (currently alwaysSPONSORED_TYPE
);sponsee: address
- address of the sponsee;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 intoTXCALL
;value: uint256
- exact amount of Ether in wei to be received by the callee;data: bytes
- the calldata for the call intoto
; andv: uint8
,r: bytes32
,s: bytes32
- signature for the package, including chain id as specified in EIP-155.
The signature (v
, r
, s
) arguments are computed from secp256k1(keccak256(type || abi.encode(nextra, mingas, to, value, data, invoker, chainid)))
.
Outputs
TXCALL
pushes the following two values onto the stack:
top - 0 |
top - 1 |
---|---|
success |
calleeSuccess |
success
success
shall be zero in the following cases:
type != SPONSORED_TYPE
- Invalid signature
- The address recovered from
v
,r
, ands
does not matchsponsee
- Gas limit supplied with the call into
TXCALL
is less than the signedmingas
- 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
) andvalue
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.
Return Data
The memory region defined by retOffset
and retLength
shall be filled in the same way as the CALL
instruction with similar arguments.
The return data area accessed with RETURNDATASIZE
(0x3d
) and RETURNDATACOPY
(0x3e
) shall be set in the same way as the CALL
instruction.
Gas Fees
The gas fees for TXCALL
are calculated according to the following pseudo-code:
S_cd = len(data) # In 256-bit words, rounded up
fees = 3200 + (6 * S_cd)
if preconditions_good(...):
return fees + cost_of_call(...)
else:
return fees
Where len(data)
is the length of the region of memory defined by argsOffset
and argsLength
, rounded up to the nearest 256-bit word, and cost_of_call(...)
is the cost of a CALL
(0xF1
) instruction with the same gas
, value
, argsOffset
, argsLength
, retOffset
, and retLength
arguments.
Rationale
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.
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.
Reserving an EIP-2718 Transaction Type
While clients should never directly interpret transaction-like packages as true transactions, reserving an EIP-2718 transaction type for transaction-like packages reduces the likelihood of a transaction-like package being misinterpreted as a true transaction.
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, 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.
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.
Lack of Replay Protection
Earlier approaches to this problem included mechanisms for replay protection. This proposal explicitly does not handle replay protection, but instead includes a signed-but-unused field (nextra
) which is expected to be used by invoker contracts to implement replay protection. Delegating replay protection to the invoker sidesteps the issue of giving a precompile contract its own storage, while opening the door to more innovative replay protection methods in the future.
Backwards Compatibility
No known issues.
Test Cases
TODO
Implementation
TODO
Security Considerations
Reentrancy
- Checking
msg.sender == tx.origin
no longer prevents reentrancy.
Signature Verification & Reply Protection
- Potential impersonation attacks if there is a bug in the signature verification.
- Replay protection can be poorly implemented (or even maliciously broken) in the invoker.
Frontrunning
- Transaction-like packages can be extracted from the original sponsor's transaction and resent by another sponsor.
Copyright
Copyright and related rights waived via CC0.