1.Summary
This proposal from BNB Chain Core Team to allows Layer 2 networks that build on OP Stack to define its own gas token independently, instead of being limited to Layer 1’s gas token.
2.Abstract
In the Ethereum Virtual Machine (EVM), a transaction call can be simply represented as a tuple {from, to, value, data, gaslimit}. OP Stack has implemented a seamless cross-chain transaction call between L1 and L2 layers: A transaction call happens on the source chain and will be fully executed on the target chain. Introducing the custom gas token will fundamentally change the meaning of the value field in the tuple: the different gas tokens on L1 and L2 mean that the value of gas tokens is no longer equal. By adjusting the token handling logic in the cross-chain communication layer(Portal and L2toL1MessagePasser), OP Stack can keep the semantic of cross-chain transaction calls the same, reducing the impact on other components.
The fee of cross-chain transactions is influenced by custom gas tokens due to the different prices of gas tokens. By implementing a token price oracle and considering token prices for fee calculations, the system can still maintain financial balance even if the income and expenses are two distinct tokens.
3.Motivation
Many projects aspire to deploy their own layer2 or even layer3 solutions for various reasons:
- Low Transaction Fees: Scenarios like GameFi, SocialFi, and DEX platforms demand extremely cost-effective transaction fees.
- Customized Chain Requirements: Projects often require customized features and rapid iterations such as precompiled contracts, shorter block times, and customized Abstract Account solutions.
They often want to enhance project value by issuing tokens that can serve as gas tokens on Layer 2. However, OP Stack currently lacks support for this feature. Therefore, this draft focuses on enabling custom gas tokens on the OP Stack codebase.
4.Specification
The current OP Stack’s cross-chain communication follows a layered model comprising application layer and communication layer.
4.1 Communication Layer
The communication layer is accessible without permission. Developers can build their cross-chain applications on this communication layer, and native Token Bridge is one of the applications.
The communication layer is primarily responsible for two key functions.:
- Implement cross chain transaction calls. This is achieved through the collaboration of Portal, MessagePasser contracts on two chains, along with op-node. The cross chain call can be represented as {from, to, mintValue, value, data, gaslimit}, the mintValue means the amount of minted L2 gas token when deposit to L2, the value means the the transfer amount of L2 gas token to the to account.
- Verification of Cross-Chain messages. In the process of L1 to L2, the op-node observes the events on L1 and includes deposit transactions into blocks, verification passes only if it can reach state consensus. The tx from L2 to L1 is verified through Merkel proofs and fraud proofs.
The introduction of custom gas tokens mainly impacts the ‘value’ field in cross-chain transaction calls. To remove ambiguity about the “value” on both chains, we get two options here.
4.1.1 Option1: Enhance Cross Chain Transaction Call
A cross-chain transaction call can be represented as:{from, to, mintValue, Value, remoteMintValue, remoteValue, data, gaslimit}. remoteMintValue and remoteValue refer to the amount of gas token on another chain in a cross-chain transaction. The Portal, MessagePasser and also the EVM need to adapt to this change to handle the remote tokens.
For example, the depositTransaction of Portal need to charge the _remoteValue of custom gas token in ERC20 format, the logic will be like:
On the other hand, when the L2 EVM handles the DepositTx, it will require to mint the L1 gas token on L2 in ERC20 format and transfer to the target account. These happen during the EVM transaction pre-execution phase, not within smart contracts.
4.1.2 Option2: Wrap Cross Chain Transaction Call
For L1 to L2 transaction calls, invoking Portal with msg.value is no longer allowed, a new parameter ‘mintValue’ will be introduced. The Portal needs to transfer the mintValue amount of L2 custom gas token in ERC20 format from msg.sender to itself. The previous opaqueData = abi.encodePacked(msg.value,_value,_gasLimit,_isCreation,_data) should be change to opaqueData = abi.encodePacked(‘mintValue’,_value,_gasLimit,_isCreation,_data) in the Portal contract.
For L2 to L1 transaction calls, invoking L2toL1MessagePasser with msg.value is no longer allowed, a new parameter ‘callValue’ will be introduced. The L2toL1MessagePasser needs to transfer the callValue amount of L1 gas token in ERC20 format from msg.sender to itself. The WithdrawalTransaction in L2toL1MessagePasser will be changed from { nonce: messageNonce(), … value: msg.value…} to { nonce: messageNonce(), … value: callValue…}
4.1.3 Comparison
Option1’s framework is clearer but will require changes across multiple modules, including op-node and EVM. Option 2 is a simple and lightweight solution, however, its capability is slightly weaker than option 1. Overall, the architecture of option1 is better .
4.2 Application Layer
The Messenger and Bridge modules together form the entire application, enabling tokens to flow freely between two chains. Messenger manages message nonces and failure retry mechanisms. Bridge acts as the gateway, providing user interfaces and managing token mapping relationships.
The introduction of custom gas primarily impacts the Bridge module in two aspects:
- interfaces changed; Introduce two new interfaces depositGasToken and withdrawGasToken to reduce confusion, along with their corresponding finalize interface on the other chain.
- the processing logic of gas tokens on both chains changed. Because the gas token is an ERC20 token on the other chain, this part should be properly handled.
4.3 L1 to L2 Fee
When a user initiates a deposit transaction on Layer 1 and specifies a gas limit, this transaction will ensure that an equivalent amount of gas limit is executed or burned on Layer 1 as a form of fee charge. This mechanism serves to prevent DoS attacks on Layer 2 through cross-chain transactions.
If L2 adopts the custom gas token solution, there will be no need to charge fees by burning gas tokens on L1. When the gas limit exceeds a certain threshold, an amount of gaslimit * L2 base fee of L2 custom gas token will be transferred from the user’s account to a treasury account in ERC20 format. In the ResourceConfig contract of L1, there are two parameters: minimumBaseFee and maximumBaseFee. By considering the prices of two gas tokens, setting these two parameters appropriately can make gaslimit * L2 base fee approximately equal to the cost of executing this transaction on L2. The operator of L2 subsequently has the authority to withdraw L2 custom gas tokens from the treasury.
4.4 L2 to L1 Fee
When users send transactions on L2, they are required to pay an L1Fee to cover the costs of DA and fixed overhead. The calculation formula for L1Fee is: L1Fee = L1GasUsed * L1GasPrice * FeeScalar. The L1GasUsed is related to the length of transaction raw data and compression rate.
Considering the different prices of gas tokens on two chains, a new operator will be introduced: TokenPriceRatio. The formula will be:
L1GasPrice = L1GasPrice * TokenPriceRatio
L1Fee = L1GasUsed * L1GasPrice * FeeScalar
However, the value of TokenPriceRatio cannot be automatically calculated by the system; it requires an Oracle mechanism where an off-chain service feeds the price into the L2 contract. Price feeds come in different forms and algorithms, OP Stack can leave it to the maintainer of L2. Even if the price feed lags or is inaccurate, it won’t cause major financial losses, but may create an imbalance between income and expenses in a short period.
4.5 Wrap Gas Token
Since the gas token is a wrapped ERC20 token on another chain, the ERC20 needs to be deployed in advance and maintained as globally unique. Typically, the gas token wrapped in L1 already exists, so all that’s required is to pre-deploy the ERC20 format contract of the L1 gas token on L2. The issue of other L2 tokens remains unchanged.