Open tynes opened 9 months ago
This could be extended to support more than L1 fee abstraction but instead abstract the full fee payment. This would be more intrusive to EVM equivalence, but would enable a lot of experimentation. It is possible that only abstracting the L1 portion of the fee is enough. We would want to think through the exact data passed into the smart contract if we were abstracting the entire fee payment. Likely we would want gasUsed
, success
and the raw transaction data.
This could also be used for MEV rebates by reducing fees for users that need a rebate. A mechanism for tracking who deserves rebates would need to be developed. This could be managed by the chain operator as an oracle, or on chain applications could track this information. For example Uniswap v4 hooks could be very useful for automating the process of determining who deserves MEV rebates
I believe this proposal has great potential and is also highly flexible. I have carefully reviewed the document. However, there are some critical details that I have doubts about. I hope we can clarify these through discussion. We would like to contribute to accelerating its implementation if necessary.
Fee ratio: The exchange rate between the native token and ether on a custom gas token chain.
A solidity interface could be defined that accepts the RLP encoded transaction and potentially some other data and it is expected to return a uint256 that represents the L1 fee or the L1 gas used
For this implementation, is a fee ratio needed? If so, where should it be stored, and who should update the fee ratio as it changes frequently? If not, how should the exchange rate between ether and the native token be handled?
This could be extended to support more than L1 fee abstraction but instead abstract the full fee payment.
Since the L1 fee is used to purchase data availability for Ethereum and involves only the data size of the transaction content, it can be computed using a smart contract. However, the L2 fee involves the EVM execution process; how can this approach support it?
Regarding the fee ratio, there is no enshrined concept of a fee ratio. It is up to the chain governor to choose the implementation details of the contract that computes the fee. If the chain governor wants to use a fee ratio in their contract, they are free to do so, they could also using an oracle based an an AMM or ecdsa signature.
For this implementation, is a fee ratio needed? If so, where should it be stored, and who should update the fee ratio as it changes frequently? If not, how should the exchange rate between ether and the native token be handled?
These are implementation specific details. I am happy to provide advice on how it can be done, but ultimately all the protocol is aware of is EVM execution where bytes are passed in and the amount of gas to be charged is returned. For illiquid assets, you likely want a more centralized oracle solution that is able to push exchange rate updates directly to the L2. For liquid assets, you could use an AMM based oracle for the exchange rate.
This could be extended to support more than L1 fee abstraction but instead abstract the full fee payment.
Perhaps its best to just keep it simple and only add this sort of abstraction to the L1 portion of the fee. This would be a much more simple change. There wouldn't be a way to turn off the execution fee or modify it but I suppose that is fine.
How would this change impact the Receipt
type? It currently contains multiple L1 fee-related fields (L1GasPrice
, L1BlobBaseFee
, L1Fee
, ...), some of which were stored in the DB pre-bedrock, but are now decoded from the L1BlockInfo
tx in func (rs Receipts) DeriveFields
function.
The L1 gas price info returned from the on-chain function would then again need to be stored in DB for each Receipt
, otherwise:
Do you see re-adding some L1 gas cost fields to Receipt
as an acceptable outcome of fee abstraction change? Could be implemented similar to DepositNonce
/DepositReceiptVersion
.
@ArtificialPB I haven't thought super deeply about all of the database implications but you raise good points. You don't want to require an archive node to be able to dynamically recreate the values. It does make sense to index them with the receipt.
Right now, the L1 portion of the fee is defined in native code. With various hardforks, the fee calculations are changed. This adds tech debt to the state transition function as there becomes more branching logic depending on the currently active chain spec. For example, ecotone introduces a new fee formula and fjord may introduce a new fee formula. This means that every op stack execution client needs to support this branching logic.
It is possible to use EVM bytecode instead to define the L1 portion of the fee. A solidity interface could be defined that accepts the RLP encoded transaction and potentially some other data and it is expected to return a
uint256
that represents the L1 fee or the L1 gas used. This would remove altering the fee logic from being a hardfork and increase the social scalability of fee logic discussions as any team working on the OP Stack can choose to use their own fee formulas that work best for them. There should be some standard EVM bytecode that comes with the OP Stack that can do a good job of this fee charging so that teams don't need to think about this problem unless they really want to.There are some performance considerations of this approach. Benchmarking is required to learn how much of an impact this would have on syncing. Spinning up an EVM instance to do this calculation will always be slower than running the calculation in native code. It is likely that it should be a
STATICCALL
context, ie no writing of state because that could result in some strange side effects. The only application of writing state would be to write the L1 fee to transient storage such that smart contracts would be able to access the value only during the execution of the particular transaction, this could be useful for meta tx relaying.Another concern is how the L1 portion of the fee isn't committed to by the user's signature. There may have been some work done to attempt to standardize a "multidimensional fee transaction for L2s" that could help with this problem. If the smart contract can be swapped very quickly, then it may be possible for the network to overcharge end users for their L1 fee because they cannot express a "max amount of L1 fee" they are willing to pay. It is possible that this logic could exist in the smart contract doing the L1 fee charging itself, this could work well with smart contract wallets. This is already an issue for what its worth, as the chain operator can bump the L1 fee params in the
SystemConfig
arbitrarily.