Maybe a bit too much for this, but any thoughts about adding a token address to automatically make the payment and agreed rate of conversion? As another extension, agreement?
I’m strongly on inclusion of anything “token” related. Those things can all be handled within the EVM/SmartContract layer.
After some good conversation with @MicahZoltu:
There seem to be a number of strong cases for why gasPrice
should typicaly be under the control of the gas-payer. These are primarily centered around separation of concerns since the gas-payer is the one responsible for getting the transaction included and speed of inclusion is often a function of gasPrice
.
One case against gasPrice
being controlled by gas payer is the griefing angle for meta-transactions when the gas payer is being re-imbursed, but this can be fully mitigated at the EVM/SmartContract layer.
The cases for gasPrice
being controlled by sender are fewer, but they are compelling. The 0x protocol use the formula 150,000 * gasPrice * orders filled
to compute protocol fees. If gasPrice
is controlled by the gas payer, then someone could monitor the transaction pool for sponsored transactions, re-sign them at a higher gas price, and grief the transaction sender.
Given that there seem to be strong cases for both, we advocate supporting both via something like https://github.com/ethereum/EIPs/issues/232 which poses an extensible transaction format.
- Step one would be to introduce this new format, applied to the current legacy transaction format.
- Step two would be to introduce new formats for sponsored transactions.
Based on current thinking, there are good cases for sponsored transaction to support the following
- Sender controlled
gasLimit
andgasPrice
- Sender controlled
gasLimit
, Payer controlledgasPrice
There are 2 other potential formats that could be included if there are compelling use cases for them:
- Payer controlled
gasLimit
andgasPrice
- Sender controlled
gasPrice
, Payer controlledgasLimit
If anyone has strong cases for these formats, speak up.
We are also looking at https://github.com/ethereum/EIPs/pull/2681/files which caps the size of the transaction nonce
which is at position-0. This would have the benefit of being able to differentiate between a legacy transaction and a new-style transaction assuming that we offset the transaction versions by 2**64. I’m not advocating for this approach as it is a bit hacky and the new transaction format can already be differentiated from the legacy one by decoding the full RLP payload.
If no one has strong feelings I’ll update the EIP to have the ORIGIN
opcode refer to GAS_PAYER
only because it is less likely to block this EIP than deprecating ORIGIN
all together (my personal preference long term) and msg.sender
is already available if you need to know SENDER
address.
Contract authors have been warned since basically the beginning to not use tx.origin
and I think most static analyzers throw a warning if you use it. Also, legacy transactions would still be supported so anyone who needs tx.origin
to be equal msg.sender
of the entrypoint can still get that behavior (even though this exact behavior is what everyone says contracts should not do).
Maybe 28,000 gas as a starting point since I’m guessing the account updates are the most expensive parts, and we have to do up to 4 (sender, recipient, miner) whereas previously we had to only do up to 3 (sender, recipient, miner, gas payer) for a simple ETH transfer?
rlp([TransactionType, [...])
would be backward compatible in the sense that the two transaction types don’t overlap in their format so the client can differentiate them by the number of items in the outer RLP array once they decode. It is a bit annoying on an implementation level, but definitely possible.
I have just merged in some big changes to this EIP.
- I published a draft proposal for Typed Transaction Envelope (https://eips.ethereum.org/EIPS/eip-2718) which introduces a generalized mechanism for adding new transaction types to Ethereum. This could potentially be used for several other open EIPs such as 1559.
- I updated this EIP to leverage 2718.
- This EIP now represents 4 different transaction subtypes:
a.SENDER
setsgasLimit
&gasPrice
b.SENDER
setsgasLimit
andGAS_PAYER
setsgasPrice
c.GAS_PAYER
setsgasLimit
&gasPrice
d.GAS_PAYER
setsgasLimit
&gasPrice
andchainId
is not included. - I have updated the rationale section to discuss situations in which each of these transaction types could be useful.
- I have separated the signature y-parity bit from the
chainId
. - I updated the specification to assert that the
ORIGIN
opcode isGAS_PAYER
for these transactions.
Re (5): This increases the payload size by 1 byte but decreases complexity of signing tools notably. I suspect there will be some push back on this, but I wanted to start from “easy to read, easy to implement” and have people argue for why the increased complexity is necessary.
Regarding ORIGIN
/tx.origin
, see my comment on Typed Transaction Envelopes here. If that gets added to EIP-2718, then we can simply define TransactionType=1
transactions to have the lower 224-bits of TRANSACTION_DATA
opcode (0x32
, aka ORIGIN
, aka tx.origin
) be GAS_PAYER
.
This is far beyound the scope of this EIP. Token are not recognised by the EVM, they are just “one more contracts” and they are likelly to remain that for long. Adding that is the best way to get this EIP rejected. Again, I believe repaying should be handled by smart contracts
It sure is possible, but AFAIK, it much easier to do by adding the extra fields (needed for this EIP) at the end of the rlp encoded array … and checking appying this EIP (or not) depending on the emptiness / availability of these extra fields. I believe this is what is done with EIP155. I also believe we should get a core dev give his opinion on the best way to implement that.
→ I personnaly don’t care how the encoding is done, as long as it’s simple to implement which is what would give the best chance for this EIP to get adopted

and checking appying this EIP (or not) depending on the emptiness / availability of these extra fields. I believe this is what is done with EIP155. I also believe we should get a core dev give his opinion on the best way to implement that.
This EIP is just one of many EIPs that would benefit from a new transaction type. Some other examples include EIP-1559, Rich Transactions, Multisig transactions, etc. At the moment, we have to be very careful that all transactions are uniquely identifiable based on the number of arguments they have. The idea with EIP-2718 is that we can solve this problem once and then going forward all we have to worry about is not re-using the TransactionType
number, but we don’t have to worry about overlap between types otherwise.
Note: We should continue this particular conversation over at EIP-2718: Typed Transaction Envelope
+1 Sponsored Transactions.
Some thoughts on what to do with tx.origin
It is tempting to re-use this for GAS_PAYER
. If we go this route I would advocate for renaming this opcode ORIGIN -> GAS_PAYER
(which implies tooling like solidity would need to do this rename as well). This would be socially and technically expensive, but I think it could be a very nice cleanup.
The only argument I know of against this, beyond the social/technical cost is the backwards incompatibility issue. I think it is worth exploring how many contracts are actually making use of this opcode, and to try and objectively understand what the impact would be. My intuition is that it would be very small.
So I’m to using
tx.origin
for gas payer but only if we go all-the-way and both re-purpose it at the EVM level and rename/rebrand it at the higher levels of the tooling.
I wonder if we need to have a second chainId
for GAS_PAYER
? In theory, the sender may want a transaction to be valid on all chains but the gas payer only wants the transaction valid on one chain.

Some thoughts on what to do with
tx.origin
Let’s continue this discussion over at EIP-2718: Typed Transaction Envelope
2718 was recently updated to assert that ORIGIN
must equal CALLER
of the first frame for reasons. Either we will need a new opcode for GAS_PAYER
if we want that, or we will need to accept that sponsor payments will need to be handled some other way (not via the contract inspecting the transaction to figure out who the gas payer is at execution time).
I’m curious to hear people’s thoughts on this and how critical it is that the EVM is aware of who the gas payer is and whether we can live without it. Something to keep in mind is that for many/most transactions GAS_PAYER
will equal ORIGIN
, and introducing a GAS_PAYER
opcode enable contracts to identify the type of transaction and potentially discriminate on it. Also, adding a new opcode is a pretty big deal since the space for them is somewhat limited, and additional opcodes add even more complexity to the EVM.
We could make it a precompile rather than an opcode, that would avoid contention over the limited opcode space, but that wouldn’t address the discrimination issue.

I’m curious to hear people’s thoughts on this and how critical it is that the EVM is aware of who the gas payer is and whether we can live without it.
Although I don’t feel strongly either way, I believe GASPAYER
is not critical. EIP-2711 does not resolve the atomicity requirement of meta-txs. If gas becomes unobservable, paying the relayer in a sponsored tx doesn’t make sense because they could be griefed if reverted if the signer’s action runs out of gas. Therefore a payment makes more sense to executed in separate transaction. I’ve proposed EIP-2733 which would facilitate this. The payment transaction can be hard coded to submit payment to a specific relayer.
This raises the question, which should probably be picked up in the EIP-2718 thread, but how can / should transaction envelopes support recursive definitions. For example, the ideal scenario is that EIP-2711 txs can wrap EIP-2733 txs. It’s unclear what the semantics of that should be.
After some discussion in Discord, I have made some pretty major changes to this EIP. It now adds support for Sponsored Transactions + Batch Transactions + Expiring Transactions. The idea is that each of these features may be valuable while paired with any of the other features, and trying to draft specifications that allow you to mix and match is difficult. Rather than try to solve that particular problem now, 2711 is trying to take the more expedient path of just bundling them together in this EIP.
I recommend anyone interested in this EIP review the recent changes, as they are pretty significant.
Regarding the latest version of this EIP:
Why should the signer sign secp256k1(keccak256(rlp([TransactionType, SenderPayload])))
when TransactionType
is already part of the SenderPayload
Why not just sign secp256k1(keccak256(rlp(SenderPayload)))
?
Also, in the simple summary you wrote “sposored” instead of “sponsored”

Why should the signer sign
secp256k1(keccak256(rlp([TransactionType, SenderPayload])))
whenTransactionType
is already part of theSenderPayload
SenderPayload
has the TransactionSubtype
, but not the TransactionType
.
Will fix the sponsored typo in the morning. I have fixed the sponsored typo.

SenderPayload
has theTransactionSubtype
, but not theTransactionType
.
My bad, I got confused
I have made 2 normative changes to the EIP:
- I have updated it to specify what Type 2 Transaction receipts look like, per recent changes in EIP-2718 (which requires each transaction subtype define its receipt
Payload
). - I changed the child transaction array into a one dimensional array. This trades ~1% to ~5% size on the wire in exchange for easier human readability/understanding (an array of tuples is easier to grok and describe and talk about than a giant one dimensional array with repeated contents).
As always, feedback welcome!