EIP-2711: Separate gas payer from msg.sender

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 :slight_smile:

+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 :+1: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.

1 Like

Let’s continue this discussion over at EIP-2718: Typed Transaction Envelope - #11 by MicahZoltu

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.

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.

1 Like

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”

1 Like

SenderPayload has the TransactionSubtype, but not the TransactionType.

Will fix the sponsored typo in the morning. I have fixed the sponsored typo. :slight_smile:

My bad, I got confused :confused:

I have made 2 normative changes to the EIP:

  1. 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).
  2. 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!

Not sure if I missed this when skimming up top but is there a reason that it’s preferable to have subtypes [1-4] instead of the type item of the transaction envelope?

See the Rationale section. It was mostly for bookkeeping reasons:

[…] each of the subtypes could be a unique TransactionType. The reason we chose to go with a single EIP with subtypes is because these 4 transactions all have a lot in common and each separate EIP would be almost identical to the previous. We felt that in this case, splitting into multiple EIPs wasn’t worth the duplication of EIP content.

I wouldn’t be too opposed to having them be 4 separate transaction types, but one EIP. It would save us a byte :man_shrugging: When I wrote the EIP originally it was hard to structure and reason about when they were separate types which is the main reason I switched to subtypes. If people believe that this isn’t important enough, or have suggestions on how to structure the EIP so it is easy to understand with different types I’m open to it.

An example of where things get a bit complicated is that the SenderPayload includes a bit of data from outside the inner transaction, which means the thing signed is a merge of the outer and inner transactions. Certainly not insurmountable, just more complicated.

I appreciate the Rationale writeup of ValidUntil as timestamp instead of block number.

I just wanted to note some downsides of timestamp, and the proposed workarounds, like:

  • It’s harder to use validUntil to prevent the transaction being valid at the next fork (which is currently triggered by block number). Recommendations:
    • Estimate block number, adjusting based on tolerance for accidental inclusion in next fork
    • Advocate for EIP-2456 to activate forks at a timestamp
  • Other scenarios might have the same pattern as above, like the proposed ReGenesis.
    • Advocate for timestamp-based activation of ReGenesis

In both of the cases you have mentioned, I advocate for switching to timestamp-based activation. :smile:

1 Like

Hey guys, I’ve been coding some stuff using the multicall pattern, and realized that batch transactions would be similar but with even better UX.

I have two questions on how this would work for users:

  1. Would the base transaction fee be per transaction or per batch?
  2. Would it be possible to revert a batch if one of its transactions revert?

@albertocuestacanada I recommend checking out https://eips.ethereum.org/EIPS/eip-3074 for the latest thing we are all pushing for to achieve transaction “batching”. This EIP will probably get withdrawn at some point, just leaving it open for now until we settle on something (which is currently looking like 3074).

2 Likes

I agree that this should be included with the transaction batching EIP. It seems that they would be used together anyway.

If 3074 is included in a hard fork, I’ll probably close this one because it is no longer necessary/useful/interesting at that point.