-
Notifications
You must be signed in to change notification settings - Fork 46
feat: add custom gas token #305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: add custom gas token #305
Conversation
Signed-off-by: Joxes <[email protected]>
Removing the ETH Compatibility section, as there are no relevant differences to note. Signed-off-by: Joxes <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a new Custom Gas Token (CGT) design for OP Stack chains that enables using assets other than ETH as the native fee currency. The design replaces the previous experimental approach with a minimal, flexible architecture that decouples native asset management from core system components.
Key changes:
- Introduces
isCustomGasToken()
flag to disable ETH transfers in bridging methods - Adds two new predeploys:
NativeAssetLiquidity
for asset storage andLiquidityController
for supply management - Enables flexible native asset value assignment through governance-controlled minting mechanisms
Comments suppressed due to low confidence (3)
protocol/custom-gas-token.md:3
- Author name 'Skeletor' appears to be a placeholder or fictional character name rather than a real author name for a technical design document.
| Author | *AgusDuha, Joxes, Skeletor* |
protocol/custom-gas-token.md:292
- Spelling error: 'granteed' should be 'granted'.
- Any minters granteed to interact with the `LiquidityController` require proper audits to ensure native asset logic can’t be broken in production, as the recovery would be costly.
protocol/custom-gas-token.md:294
- Grammar error: 'or minters to withdraw' should be 'or allowing minters to withdraw'. Also,
CustomAssetLiquidity
should beNativeAssetLiquidity
to match the contract name used elsewhere.
- There is an open discussion on how to support tokens that have other than 18 decimals. This is a concern for the minter that is placed on top of the `LiquidityController`.
excellent job for this! |
protocol/custom-gas-token.md
Outdated
| Native asset is bridgeable? | Yes, through `DepositERC20Transaction` and native withdrawals. | Yes, but not enshrined in core contracts. The chain governor must implement custom logic to enable it, e.g., coupling bridging with the `LiquidityController`. | | ||
| Token Implementation Flexibility | Restricted to 18 decimals and transfer properties. | There are potentially no limitations, as long as it is coupled adequately with `NativeAssetLiquidity`. | | ||
| WETH predeploy | Reserved for the wrapped version of the custom gas token, taking metadata from `L1Block` (`SystemConfig`). | Reserved for the wrapped version of the custom gas token. Metadata is taken from `L1Block` (`LiquidityController`). | | ||
| Native Asset Supply | Held in `OptimismPortal`, originating from the original L1 token contract. | Minted at genesis via `NativeAssetLiquidity`. Manageable under any rules, through the controller, which may depend on an existing ERC20. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For chains that use existing CGT will it be expected to move existing L1 token supply from OptimismPortal to L1CGTStandardBridge or will L1CGTStandardBridge rather manage the supply in OptimismPortal ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, chains need to migrate the liquidity held in OptimismPortal
into their implemented custom bridge.
- There are two potential paths to minimize the impact: adding rate limits, or minters to withdraw the needed supply and virtually “close” or don’t need to use the `CustomAssetLiquidity` anymore. | ||
- There is an open discussion on how to support tokens that have other than 18 decimals. This is a concern for the minter that is placed on top of the `LiquidityController`. | ||
- One possible solution might be adding `decimals()` in the `LiquidityController`, or fully handling it through the minters. | ||
- Existing OP Stack chains using old designs would need to upgrade to the new version, the solution of which is actively being architected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you share more info if you can. Is there a plan to make it work out of the box or are there expected any additional steps from existing OP chains with CGT ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to offer some out-of-the-box features, and at the same time, allow enough flexibility for the liquidity management criteria that the chain wants to implement.
Signed-off-by: Joxes <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Yes, one of the goals is to allow migrations! |
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
…mentation Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
A poc implementation can be found here: defi-wonderland/optimism#478 |
|
||
The CGT sets `Types.WithdrawalNetwork.L2` as chain type in each `FeeVaults` contracts on the constructor, without requiring contract changes. Funds are going to be sent to a desired L2 address. | ||
|
||
To accurately charge the fees for execution and data availability, chain governors may now adjust a `minBaseFee` and `operatorFee`. In the future, other parameters or mechanisms might be included to properly account for the cost for each activity, such as adding a price oracle that converts data cost expressed in ETH into the ASSET. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you expand more on how these two parameters should be used to charge for fees? When would you adjust each and how do you know what to set it to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a design where the fee is computed through a static call to a smart contract that could help to compute the CGT/ETH ratio: ethereum-optimism/op-geth@optimism...teaxyz:tea-geth:optimism
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you expand more on how these two parameters should be used to charge for fees? When would you adjust each and how do you know what to set it to?
We need a way that can approximate good values for the min basefee and operator fee that can approximate the pricing of the token denominated in ETH. This should exist as a CLI tool so that its easy to run and get the right values depending on different assumptions (token price relative to ETH)
- `OptimismPortal` and `L2ToL1MessagePasser` don’t contain the API anymore to bridge native assets. | ||
- Native ETH bridging is disabled, now enabled through L1-WETH, minting an `OptimismMintableERC20` representation. | ||
- Supersim needs to be aware when CGT is being used. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't seen this aspect of the design mentioned anywhere else, but it sounds like the L1CGT bridge is now the entry point for all ETH/native asset transfers? This is a breaking change we'll need to make sure we communicate, possibly requiring viem changes also, cc @fainashalts @ZakAyesh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Until now, when the chain uses ETH as native currency, it uses the typical Standardbridge
/ CrossDomainMessenger
/ OptimismPortal
/ L2ToL1MessagePasser
flows, this is untouched.
When isCustomGasToken
is marked as true, it disables all the bridging flow for ETH (msg.value
) above, and then it could be replaced by a CGTBridge
as we described as a way to bridge the native asset.
- There is an open discussion on how to support tokens that have other than 18 decimals. This is a concern for the minter that is placed on top of the `LiquidityController`. | ||
- One possible solution might be adding `decimals()` in the `LiquidityController`, or fully handling it through the minters. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is solving this a blocker to finalizing/merging this design doc? I think it should be as it feels like a fundamental thing and we want to be certain it doesn't require nontrivial design changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are examples of chains using tokens that have decimals other than 18 as their gas token: for instance Circle's newly announced chain that will USDC for gas (6 decimals):
https://www.circle.com/blog/introducing-arc-an-open-layer-1-blockchain-purpose-built-for-stablecoin-finance
protocol/custom-gas-token.md
Outdated
|
||
## Summary | ||
|
||
The proposed Custom Gas Token upgrade lets any OP Stack chain introduce its native asset as the gas currency with almost no core-code intrusion: a single `isCustomGasToken()` flag turns off ETH transfer flows in all bridging methods, while three new pre-deploys, `NativeAssetLiquidity`, a contract with pre-minted assets, `LiquidityController`, an owner-governed mint/burn router, and `L2CGTBridge`, an reserved address that contains a contract with the API calls, hand supply control to chain governors or authorized “minter” contracts that can plug in anything from ERC-20 converters to third-party bridgind models or emission schedules. Wrapped-asset compatibility is preserved, and the entire system launches at genesis by funding the vault and letting the governor release an initial working balance. Overall, the design keeps the OP Stack lean, token-agnostic, and future-proof while unlocking custom economics and flexibility to make the native asset expressive in its manner. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of merging LiquidityController and NativeAssetLiquidity? We have a lot of contracts, and these two are fairly small and logically related, so combining them might be simpler
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, this will make things simpler. One reason we did this separation is to mirror the ETHLiquidity
& SuperchainETHBridge
, we envisioned ETHLiquidity
might be fused with NativeAssetLiquidity
The prior CGT design anchored the gas token to an L1 ERC‑20, hard‑coding bridge paths, and cluttering core contracts with token metadata. These restrictions make it hard to handle the following scenarios properly: | ||
|
||
- Integrates with a token that doesn’t live on L1. | ||
- Launch chains whose native asset does not yet exist or have an ERC20 representation somewhere. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What restrictions are there on the ERC20? Lots of edge cases to consider https://github.com/d-xo/weird-erc20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are no restrictions on the type of ERC20 because the token bridge is not coupled to the design. A bridge can be built that supports any sort of token, even non standard ones. When we build a token bridge, we will likely make it work with tokens that have 18 decimals and are a standard ERC20 token
|
||
TBD. | ||
|
||
## Impact on Developer Experience |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing that would be helpful is architecture diagrams showcasing the user flows/entrypoints and token flows for various user actions based on configs, where the tree of possible flows is the combinations of:
- Gas token is ETH vs. ERC20 token
- Gas token is L1 native vs. L2 native
- User is bridging ETH vs. ERC20
- User is bridging from L1 to L2 vs. from L2 to L1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added! Let me know if you like it
Something that we need to be explicit about is how the deployment of these contracts are handled. Per the current implementation (defi-wonderland/optimism#478) we will only deploy the contracts if it is a custom gas token chain and we need to initialize them with some chain specific config. This means that the op-node rollup config needs to have the following information: |
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
This is WIP so far but meant to show how it can work. The big todo is to rename the feature flag with the name of the hardfork that the CGT upgrade is included in. This does leak knowledge of CGT into the client software so that it can optionally deploy the CGT predeploys. It is expected that the CGT predeploys will be in the genesis if the hardfork is active at genesis only on CGT chains. Relevant links: - ethereum-optimism/design-docs#305 - ethereum-optimism/design-docs#313 - defi-wonderland#478
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
A code example of both contracts would look like this: | ||
|
||
```solidity | ||
contract NativeAssetLiquidity { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the only contract that can call this contract is the LiquidityController, does it make sense for the contracts to be separate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The general idea of separating them was to reduce the amount of logic in the liquidity contract to the most bare minimum given if there is a bug in it, its game over because an extreme amount of native asset could be minted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that the fewer lines of code, the lower the probability of error. However, having separate contracts means every mint and burn takes more gas. Also, given the LiquidityController completely controls the NativeAssetLiquidity contract, it will come down to the security of the LiquidityController contract.
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
Signed-off-by: Joxes <[email protected]>
Description
This document introduces a new design for enabling Custom Gas Token ("CGT") support on OP Stack. It replaces the previous experimental approach with a minimal, flexible, and future-proof architecture. The goal is to support a wide range of use cases while laying the groundwork for standardization across the ecosystem.