From 14633906a5d20739209479e310d2446596fc204c Mon Sep 17 00:00:00 2001 From: soyboy Date: Tue, 9 Dec 2025 15:11:21 -0800 Subject: [PATCH 1/3] docs: add Custom Gas Token v2 documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add comprehensive documentation for Custom Gas Token (CGT) v2: - Feature overview in OP Stack Features section - Deployment guide for chain operators - Updated fact sheet to reflect CGT support - Navigation updates in docs.json The CGT v2 implementation (introduced in Upgrade 18, op-contracts/v6.0.0) enables OP Stack chains to use any asset as their native fee currency through a flexible, application-layer architecture with two new predeploy contracts: NativeAssetLiquidity and LiquidityController. Documentation includes: - Architecture overview with mermaid diagrams - Deployment steps using op-deployer (with TODOs for specific commands) - Configuration examples and best practices - Risk considerations and troubleshooting - Cross-references between feature overview and deployment guide 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .../features/custom-gas-token-guide.mdx | 407 ++++++++++++++++++ docs.json | 2 + op-stack/features/custom-gas-token.mdx | 98 +++++ op-stack/introduction/fact-sheet.mdx | 4 +- 4 files changed, 509 insertions(+), 2 deletions(-) create mode 100644 chain-operators/guides/features/custom-gas-token-guide.mdx create mode 100644 op-stack/features/custom-gas-token.mdx diff --git a/chain-operators/guides/features/custom-gas-token-guide.mdx b/chain-operators/guides/features/custom-gas-token-guide.mdx new file mode 100644 index 000000000..e29865ff5 --- /dev/null +++ b/chain-operators/guides/features/custom-gas-token-guide.mdx @@ -0,0 +1,407 @@ +--- +title: Deploy a Custom Gas Token chain +description: Learn how to deploy a Custom Gas Token chain using OP Deployer. +--- + +This guide provides instructions for chain operators who want to deploy a Custom Gas Token (CGT) chain. +See the [Custom Gas Token overview](/op-stack/features/custom-gas-token) for a general understanding of this OP Stack feature. + +A Custom Gas Token chain enables you to use any asset as the native fee currency instead of ETH. This could be an existing L1 ERC-20 token, an L2-native token, or an entirely new asset created at genesis. + + +Custom Gas Token v2 is a new implementation that is not compatible with legacy CGT chains. +There is currently no migration path from legacy CGT to CGT v2, though one is planned to be put together. + + +## Prerequisites + +Before deploying a CGT chain, ensure you have: + +todo: provide op-deployer release version +* **OP Deployer installed**: See [OP Deployer installation](/chain-operators/tools/op-deployer/installation) for setup instructions +* **L1 RPC endpoint**: Access to an Ethereum L1 node for deployment +* **Funded deployer account**: ETH for L1 gas costs during deployment +* **Token design**: Clear plan for your native asset (supply, distribution, bridging mechanism) +* **Security audit**: Thorough review of any authorized minters or bridge contracts you plan to deploy + +## Deployment steps + +Deploying a CGT chain follows the standard OP Stack deployment process with additional configuration for Custom Gas Token specific parameters. + + + + Create a new intent file using OP Deployer's init command: + + ```bash + op-deployer init \ + --l1-chain-id \ + --l2-chain-ids \ + --outdir ./deployment \ + --intent-type standard + ``` + + This creates an `intent.toml` file in the `./deployment` directory. + + + + Open your `intent.toml` file and add the Custom Gas Token configuration. Below is an example with CGT-specific fields: + + ```toml + configType = "standard" + l1ChainID = 11155111 + fundDevAccounts = false + useInterop = false + l1ContractsLocator = "tag://op-contracts/v6.0.0" + l2ContractsLocator = "tag://op-contracts/v6.0.0" + + [superchainRoles] + proxyAdminOwner = "0xYourMultisigAddress" + protocolVersionsOwner = "0xYourMultisigAddress" + guardian = "0xYourMultisigAddress" + + [[chains]] + id = "0x0000000000000000000000000000000000000000000000000000000000001234" + + # Custom Gas Token Configuration + useCustomGasToken = true + customGasTokenName = "My Custom Token" + customGasTokenSymbol = "MCT" + customGasTokenDecimals = 18 + initialLiquiditySupply = "1000000000000000000000000000" # 1 billion tokens with 18 decimals + + # Fee configuration - adjust for your token's value + minBaseFee = "1000000000" # Adjust based on token economics + operatorFee = "1000000" # Adjust based on DA costs + + # Fee vault recipients + baseFeeVaultRecipient = "0xYourFeeRecipientAddress" + l1FeeVaultRecipient = "0xYourFeeRecipientAddress" + sequencerFeeVaultRecipient = "0xYourFeeRecipientAddress" + operatorFeeVaultRecipient = "0xYourFeeRecipientAddress" + + # Standard EIP-1559 parameters + eip1559DenominatorCanyon = 250 + eip1559Denominator = 50 + eip1559Elasticity = 6 + + [chains.roles] + l1ProxyAdminOwner = "0xYourMultisigAddress" + l2ProxyAdminOwner = "0xYourMultisigAddress" + systemConfigOwner = "0xYourMultisigAddress" + unsafeBlockSigner = "0xYourSequencerAddress" + batcher = "0xYourBatcherAddress" + proposer = "0xYourProposerAddress" + challenger = "0xYourChallengerAddress" + ``` + + ### Key CGT configuration fields + + | Field | Description | Required | + |-------|-------------|----------| + | `useCustomGasToken` | Enable Custom Gas Token mode | Yes | + | `customGasTokenName` | Name of the native asset (e.g., "My Custom Token") | Yes | + | `customGasTokenSymbol` | Symbol for the native asset (e.g., "MCT") | Yes | + | `customGasTokenDecimals` | Token decimals (must be 18) | Yes | + | `initialLiquiditySupply` | Initial supply minted to NativeAssetLiquidity at genesis | Yes | + | `minBaseFee` | Minimum base fee in native token units | Yes | + | `operatorFee` | Operator fee to cover DA costs | Yes | + + + **Fee parameter calculation is critical**: Your `minBaseFee` and `operatorFee` must accurately account for L1 gas costs and DA fees denominated in your custom token. If set too low, your chain may not cover operational costs. If set too high, users will pay excessive fees. + + + + **Decimal support**: CGT v2 currently supports only 18-decimal tokens. Support for other decimals may be added in future releases. + + + + + Deploy your L1 contracts using OP Deployer: + + ```bash + op-deployer apply \ + --l1-rpc-url \ + --private-key \ + --workdir ./deployment + ``` + + This deploys all necessary L1 contracts including `SystemConfig` with the `isCustomGasToken` flag enabled, which instructs L1 contracts to reject ETH-value transactions. + + + The deployment process will automatically deploy the CGT-specific predeploys (`NativeAssetLiquidity` and `LiquidityController`) during genesis initialization. + + + + + After L1 deployment completes, initialize your L2 genesis: + + ```bash + # TODO: Add specific genesis initialization command for CGT chains + # This will create genesis.json with: + # - NativeAssetLiquidity predeploy at 0x4200000000000000000000000000000000000024 + # - LiquidityController predeploy at 0x4200000000000000000000000000000000000025 + # - Initial supply minted to NativeAssetLiquidity + # - L1Block configured with isCustomGasToken flag + ``` + + The genesis configuration automatically: + * Creates the `NativeAssetLiquidity` contract with your specified initial supply + * Deploys the `LiquidityController` with configured token metadata + * Sets the `isCustomGasToken` flag in `L1Block` to prevent ETH operations on L2 + * Configures fee parameters in `SystemConfig` + + + + After genesis initialization, configure the liquidity controller and authorize initial minters. You'll need to: + + **1. Verify deployment** + + Check that the predeploys are correctly configured: + + ```bash + # TODO: Add commands to verify predeploy addresses and configuration + # Verify NativeAssetLiquidity has initial supply + # Verify LiquidityController has correct metadata + # Verify L1Block isCustomGasToken flag is true + ``` + + **2. Authorize initial minters** + + Grant minting permissions to your bridge or converter contracts: + + ```solidity + // Example: Authorize a bridge contract to mint native assets + // This is typically done by the ProxyAdmin owner + + // TODO: Provide specific authorization commands/scripts + // LiquidityController.authorizeMinter(bridgeAddress) + ``` + + + **Security critical**: Any address granted minting permissions can unlock native assets from the liquidity pool. Ensure all authorized minters are thoroughly audited and secured with appropriate access controls. + + + **3. Implement rate limiting (recommended)** + + Consider implementing rate limits on authorized minters to reduce risk: + + ```solidity + // TODO: Provide rate limiting implementation examples or references + ``` + + + + Start your OP Stack services with CGT-aware configuration: + + **op-geth** + + ```bash + # TODO: Add CGT-specific op-geth configuration if needed + # Standard op-geth configuration should work + ``` + + **op-node** + + ```bash + # TODO: Add CGT-specific op-node configuration + # Rollup config must have isCustomGasToken flag set + ``` + + **op-batcher** + + ```bash + # TODO: Add CGT-specific batcher configuration + # Standard batcher configuration should work + ``` + + **op-proposer** + + ```bash + # TODO: Add CGT-specific proposer configuration + # Standard proposer configuration should work + ``` + + + Your rollup configuration file must include `"isCustomGasToken": true` to ensure all services correctly handle CGT mode. + + + + + Deploy your application-layer bridge or converter contracts. The specific implementation depends on your use case: + + ### Option A: L1 ERC-20 bridging + + If you're bridging an existing L1 ERC-20 token: + + ```mermaid + sequenceDiagram + participant User + participant L1Bridge + participant L1Messenger + participant L2Bridge + participant LiquidityController + participant NativeAssetLiquidity + + User->>L1Bridge: Deposit ERC-20 + L1Bridge->>L1Bridge: Lock/Burn ERC-20 + L1Bridge->>L1Messenger: Send message + L1Messenger->>L2Bridge: Relay message + L2Bridge->>LiquidityController: mint() + LiquidityController->>NativeAssetLiquidity: withdraw() + NativeAssetLiquidity->>User: Native assets + ``` + + **1. Deploy L1 bridge contract** + + ```bash + # TODO: Provide L1 bridge deployment commands/scripts + # Bridge must be authorized as minter on L2 + ``` + + **2. Deploy L2 bridge contract** + + ```bash + # TODO: Provide L2 bridge deployment commands/scripts + # Must be authorized by LiquidityController + ``` + + **3. Authorize bridge as minter** + + ```bash + # TODO: Provide authorization commands + # LiquidityController.authorizeMinter(l2BridgeAddress) + ``` + + ### Option B: L2-native token + + If you're creating an L2-native asset with no L1 equivalent: + + ```bash + # TODO: Provide configuration for L2-native tokens + # Define initial distribution mechanism + # Configure authorized minters (DEX, rewards contract, etc.) + ``` + + ### Option C: Custom converter + + For advanced use cases with custom conversion logic: + + ```bash + # TODO: Provide custom converter implementation guidance + # Reference template contracts (when available) + ``` + + + **Templates coming soon**: The OP Stack team is developing standard bridge and converter templates to simplify integration. Check back for updates. + + + + + Before going live, thoroughly test your CGT chain: + + **1. Verify flag alignment** + + ```bash + # Check L1 SystemConfig.isCustomGasToken() returns true + # Check L2 L1Block.isCustomGasToken() returns true + # Verify both flags match + ``` + + **2. Test native asset operations** + + ```bash + # Test minting native assets via authorized minter + # Test burning native assets + # Test fee payments in native token + # Verify fee vault accumulation + ``` + + **3. Test ETH rejection** + + ```bash + # Attempt ETH deposit via OptimismPortal (should fail) + # Attempt ETH withdrawal via L2ToL1MessagePasser (should fail) + # Verify ETH operations are properly blocked + ``` + + **4. Test bridge functionality** + + ```bash + # Test deposits (L1 → L2 native asset minting) + # Test withdrawals (L2 native → L1 token) + # Verify proper locking/unlocking in liquidity contract + ``` + + + +## Post-deployment considerations + +### Supply management + +After deployment, you can: + +* **Withdraw excess liquidity**: If genesis created more supply than needed, withdraw and burn via `L2ToL1MessagePasser` +* **Add new minters**: Authorize additional contracts to mint native assets as your ecosystem grows +* **Revoke minters**: Remove authorization from compromised or deprecated contracts +* **Implement rate limits**: Add safeguards to control minting velocity + +### Fee parameter adjustments + +Monitor your chain's operational costs and adjust fee parameters as needed: + +* **minBaseFee**: Adjust based on L1 gas costs and your token's value +* **operatorFee**: Adjust based on data availability costs +* Use `SystemConfig.setGasConfig()` to update parameters + +### Developer documentation + +Create clear documentation for your users covering: + +* How to acquire native assets (bridge, DEX, faucet, etc.) +* Bridge contract addresses and interfaces +* Fee structure and token economics +* Wallet configuration (RPC endpoints, chain ID, token metadata) + +## Troubleshooting + +### Flag mismatch errors + +**Symptom**: Transactions failing with "custom gas token mismatch" errors + +**Solution**: Verify that `SystemConfig.isCustomGasToken()` on L1 and `L1Block.isCustomGasToken()` on L2 return the same value. If mismatched, this indicates a critical configuration error. + +### Fee parameter issues + +**Symptom**: Chain operator losing money on transaction costs or users complaining about excessive fees + +**Solution**: Review and recalculate your `minBaseFee` and `operatorFee` parameters based on: +* Current L1 gas prices +* Your token's market value or peg +* Data availability costs +* Target fee structure for users + +### Liquidity depletion + +**Symptom**: Minting transactions failing due to insufficient liquidity + +**Solution**: +* Check `NativeAssetLiquidity` balance +* If depleted, this indicates an imbalance between minting and burning +* Review bridge logic to ensure burns are occurring correctly +* Consider increasing initial liquidity supply in future deployments + +### Unauthorized minting attempts + +**Symptom**: Unauthorized addresses attempting to mint native assets + +**Solution**: +* Review access control configuration on `LiquidityController` +* Ensure only audited and secured contracts are authorized +* Implement rate limiting if not already in place +* Consider revoking and re-authorizing with additional safeguards + +## Resources + +* [Custom Gas Token feature overview](/op-stack/features/custom-gas-token) +* [Custom Gas Token design specification](https://github.com/ethereum-optimism/design-docs/blob/main/protocol/custom-gas-token.md) +* [OP Deployer documentation](/chain-operators/tools/op-deployer/overview) diff --git a/docs.json b/docs.json index a43257a7b..788cb1d99 100644 --- a/docs.json +++ b/docs.json @@ -1807,6 +1807,7 @@ { "group": "Features", "pages": [ + "chain-operators/guides/features/custom-gas-token-guide", "chain-operators/guides/features/setting-min-base-fee", "chain-operators/guides/features/setting-da-footprint", "chain-operators/guides/features/flashblocks-guide", @@ -2176,6 +2177,7 @@ "group": "Features", "pages": [ "/op-stack/features/flashblocks", + "/op-stack/features/custom-gas-token", "/op-stack/features/bridged-usdc-standard", "/op-stack/features/span-batches", "/op-stack/features/send-raw-transaction-conditional" diff --git a/op-stack/features/custom-gas-token.mdx b/op-stack/features/custom-gas-token.mdx new file mode 100644 index 000000000..b86d677a4 --- /dev/null +++ b/op-stack/features/custom-gas-token.mdx @@ -0,0 +1,98 @@ +--- +title: Custom Gas Token +description: Learn how utilize a Custom Gas Token for OP Stack chains. +--- + +Custom Gas Token (CGT) enables OP Stack chains to use any asset as their native fee currency instead of ETH. +This opens up new possibilities for chain operators to align their economic model with their specific use case, whether that's using a stablecoin for predictable fees, a governance token for ecosystem alignment, or creating an entirely new native asset. + +This iteration of CGT is a redesign that prioritizes flexibility, minimal core protocol changes, and future-proof standardization by decoupling native asset management from core bridging infrastructure. + +## Key features + +* **Token flexibility**: Use any token as the native gas token - existing L1 ERC-20s, L2-native tokens, or entirely new assets +* **Application-layer bridging**: No bridge or token is enshrined in the protocol; bridges and converters live entirely at the application layer +* **Flexible supply management**: Chain governors have complete control over token supply, emission schedules, and distribution mechanisms +* **Future-proof design**: Built to support emerging standards like SuperchainERC20 and cross-chain interoperability + +## How it works + +CGT is configured at genesis and comes with two new predeploy contracts to manage native assets independently from ETH bridging: + +### The `isCustomGasToken()` flag + +When enabled: + +* **On L1**: Placed in `SystemConfig`, instructs `OptimismPortal`, `L1CrossDomainMessenger`, and `L1StandardBridge` to reject transactions containing ETH value (`msg.value`) +* **On L2**: Located in `L1Block`, prevents ETH-related operations in `L2ToL1MessagePasser`, `L2CrossDomainMessenger`, `L2StandardBridge`, and `FeeVaults` + +This enables native asset mints and burns to be decoupled from deposits and moved to the application layer. + +### Two new predeploy contracts + +**NativeAssetLiquidity** + +Holds pre-minted native assets created at genesis with two core functions: + +* `deposit()`: Receives native assets (callable only by LiquidityController) +* `withdraw()`: Releases native assets to the controller + +**LiquidityController** + +Governance-controlled contract that manages asset supply through: + +* `authorizeMinter()` / `deauthorizeMinter()`: Grants or revokes minting permissions +* `mint()`: Unlocks assets from liquidity reserves for authorized parties +* `burn()`: Accepts native assets and locks them in the liquidity contract +* Stores token metadata for wrapped asset compatibility + +## Use cases + +* **Stablecoin fees**: Use USDC or other stablecoins for predictable transaction costs +* **Governance alignment**: Use your chain's governance token as the gas token to align incentives +* **L2-native economies**: Create entirely new native assets with custom supply mechanics +* **Simplified UX**: Reduce the number of tokens users need to hold for interacting with your chain + +## Comparison with previous design + +Custom Gas Token v2 was introduced in Upgrade 18 and is available in `op-contracts/v6.0.0`. + +| Aspect | Legacy CGT | CGT v2 | +|--------|-----------|---------| +| **Token basis** | Anchored to L1 ERC-20 | Independent native asset at genesis | +| **Flexibility** | Restricted to specific configurations | Supports any release mechanism | +| **Bridging** | Built into core contracts | Application-layer responsibility | +| **Supply control** | System transaction minting | Minter authorization model | +| **Adaptability** | Limited post-deployment changes | Upgradeable and flexible | + + +**Migration from legacy CGT**: There is currently no migration path from legacy CGT to CGT v2. A migration path is planned to be put together. Chains using the previous CGT design will need to coordinate a hard fork to adopt the new architecture. + + +## Developer impact + +* **Decoupled from core components**: Since native asset management is decoupled from core components, obtaining native assets might vary chain-by-chain. That means that bridging, conversions, and features utilized would be different. It's suggested to create some library or templates that cover basic uses cases (e.g., L2-native, bridging from L1) to standardize most implementations. + * Chain Governors are encouraged to audit their implementations. + * Developers would need to look at the chain's docs to understand how to obtain native assets. +* **No unified API**: The flexibility of this implementation means each CGT chain may have different methods for obtaining native assets +* **ETH bridging**: ETH bridging routes through L1-WETH as an ERC-20 wrapper +* **Documentation**: Clear documentation becomes critical for users to understand how to acquire native assets + +## Risks and considerations + +### Supply management + +* **Minter security**: Any address granted minter permissions requires thorough security review and auditing +* **Access control**: Misconfigurations in bridges or controllers could lead to unintended minting or burning +* **Rate limiting**: Consider implementing rate limits on minting velocity to reduce risk + +### Configuration accuracy + +* **Flag alignment**: `isCustomGasToken` must match between L1 and L2 to prevent protocol violations +* **Fee parameters**: `minBaseFee` and `operatorFee` must accurately account for execution and data availability costs in the native token's denomination +* **Decimal support**: CGT currently supports only 18-decimal tokens + +## Next steps + +* **For chain operators**: See [Deploy a Custom Gas Token chain](/chain-operators/guides/features/custom-gas-token-guide) for detailed deployment instructions +* **Learn more**: Read the [full design specification](https://github.com/ethereum-optimism/design-docs/blob/main/protocol/custom-gas-token.md) for technical details diff --git a/op-stack/introduction/fact-sheet.mdx b/op-stack/introduction/fact-sheet.mdx index 45307fef0..26c63b7d0 100644 --- a/op-stack/introduction/fact-sheet.mdx +++ b/op-stack/introduction/fact-sheet.mdx @@ -14,7 +14,7 @@ While the OP Stack allows for full customization, chains in the Superchain adher | **Gas limit2** | 200M | 200M | | **Blocktimes3** | 200ms | 200ms | | **Data availability support** | Ethereum | Ethereum, Celestia, EigenDA | -| **Gas token support4** | ETH | ETH | +| **Gas token support4** | ETH | ETH, Custom Gas Token | | **Upgrades** | Facilitated via OP Governance | Self-managed | | **EVM compatibility** | Equivalent | Variable | @@ -24,6 +24,6 @@ While the OP Stack allows for full customization, chains in the Superchain adher 3While protocol blocktimes can be lowered to 1 second, subsecond blocktimes can be achieved using [Rollup Boost and Flashblocks](https://writings.flashbots.net/introducing-rollup-boost). -4Although ETH is the gas token, chain operators can achieve the same UX of a custom gas token by using an ERC-20 paymaster. +4OP Stack chains can use [Custom Gas Token](/op-stack/features/custom-gas-token) to enable any asset as the native fee currency. Superchain chains use ETH as the gas token, though chain operators can achieve similar UX using an ERC-20 paymaster. From 1e45e1ad154e9836241401ee44c1ca16a2951d02 Mon Sep 17 00:00:00 2001 From: soyboy Date: Mon, 15 Dec 2025 15:57:21 -0800 Subject: [PATCH 2/3] addressing Wonderland comments --- .../features/custom-gas-token-guide.mdx | 28 +++++++------------ op-stack/features/custom-gas-token.mdx | 5 ++-- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/chain-operators/guides/features/custom-gas-token-guide.mdx b/chain-operators/guides/features/custom-gas-token-guide.mdx index e29865ff5..e3beac1ad 100644 --- a/chain-operators/guides/features/custom-gas-token-guide.mdx +++ b/chain-operators/guides/features/custom-gas-token-guide.mdx @@ -6,7 +6,8 @@ description: Learn how to deploy a Custom Gas Token chain using OP Deployer. This guide provides instructions for chain operators who want to deploy a Custom Gas Token (CGT) chain. See the [Custom Gas Token overview](/op-stack/features/custom-gas-token) for a general understanding of this OP Stack feature. -A Custom Gas Token chain enables you to use any asset as the native fee currency instead of ETH. This could be an existing L1 ERC-20 token, an L2-native token, or an entirely new asset created at genesis. +A Custom Gas Token chain enables you to use any asset as the native fee currency instead of ETH. +This asset may be an existing L1 token, a representation of a token from another chain, or a newly defined asset (or new L2 token) created at genesis. Custom Gas Token v2 is a new implementation that is not compatible with legacy CGT chains. @@ -62,17 +63,6 @@ Deploying a CGT chain follows the standard OP Stack deployment process with addi [[chains]] id = "0x0000000000000000000000000000000000000000000000000000000000001234" - # Custom Gas Token Configuration - useCustomGasToken = true - customGasTokenName = "My Custom Token" - customGasTokenSymbol = "MCT" - customGasTokenDecimals = 18 - initialLiquiditySupply = "1000000000000000000000000000" # 1 billion tokens with 18 decimals - - # Fee configuration - adjust for your token's value - minBaseFee = "1000000000" # Adjust based on token economics - operatorFee = "1000000" # Adjust based on DA costs - # Fee vault recipients baseFeeVaultRecipient = "0xYourFeeRecipientAddress" l1FeeVaultRecipient = "0xYourFeeRecipientAddress" @@ -92,19 +82,22 @@ Deploying a CGT chain follows the standard OP Stack deployment process with addi batcher = "0xYourBatcherAddress" proposer = "0xYourProposerAddress" challenger = "0xYourChallengerAddress" + + [chains.customGasToken] + name = "My Custom Token" + symbol = "MCT" + initialLiquidity = "0x..." # optional, default: type(uint248).max + liquidityControllerOwner = "0x..." # optional, default: L2ProxyAdminOwner ``` ### Key CGT configuration fields | Field | Description | Required | |-------|-------------|----------| - | `useCustomGasToken` | Enable Custom Gas Token mode | Yes | | `customGasTokenName` | Name of the native asset (e.g., "My Custom Token") | Yes | | `customGasTokenSymbol` | Symbol for the native asset (e.g., "MCT") | Yes | - | `customGasTokenDecimals` | Token decimals (must be 18) | Yes | | `initialLiquiditySupply` | Initial supply minted to NativeAssetLiquidity at genesis | Yes | - | `minBaseFee` | Minimum base fee in native token units | Yes | - | `operatorFee` | Operator fee to cover DA costs | Yes | + | `liquidityControllerOwner` | Manages the asset supply | No, `L2ProxyAdminOwner` will be used as default | **Fee parameter calculation is critical**: Your `minBaseFee` and `operatorFee` must accurately account for L1 gas costs and DA fees denominated in your custom token. If set too low, your chain may not cover operational costs. If set too high, users will pay excessive fees. @@ -146,7 +139,7 @@ Deploying a CGT chain follows the standard OP Stack deployment process with addi The genesis configuration automatically: * Creates the `NativeAssetLiquidity` contract with your specified initial supply - * Deploys the `LiquidityController` with configured token metadata + * Deploys the `LiquidityController` with configured token metadata and owner. * Sets the `isCustomGasToken` flag in `L1Block` to prevent ETH operations on L2 * Configures fee parameters in `SystemConfig` @@ -403,5 +396,4 @@ Create clear documentation for your users covering: ## Resources * [Custom Gas Token feature overview](/op-stack/features/custom-gas-token) -* [Custom Gas Token design specification](https://github.com/ethereum-optimism/design-docs/blob/main/protocol/custom-gas-token.md) * [OP Deployer documentation](/chain-operators/tools/op-deployer/overview) diff --git a/op-stack/features/custom-gas-token.mdx b/op-stack/features/custom-gas-token.mdx index b86d677a4..dfab4a6f2 100644 --- a/op-stack/features/custom-gas-token.mdx +++ b/op-stack/features/custom-gas-token.mdx @@ -74,6 +74,7 @@ Custom Gas Token v2 was introduced in Upgrade 18 and is available in `op-contrac * **Decoupled from core components**: Since native asset management is decoupled from core components, obtaining native assets might vary chain-by-chain. That means that bridging, conversions, and features utilized would be different. It's suggested to create some library or templates that cover basic uses cases (e.g., L2-native, bridging from L1) to standardize most implementations. * Chain Governors are encouraged to audit their implementations. * Developers would need to look at the chain's docs to understand how to obtain native assets. + * Ideally CGT Chain Operators can work together to formalize a common set of CGT patterns that don't come out of the box. * **No unified API**: The flexibility of this implementation means each CGT chain may have different methods for obtaining native assets * **ETH bridging**: ETH bridging routes through L1-WETH as an ERC-20 wrapper * **Documentation**: Clear documentation becomes critical for users to understand how to acquire native assets @@ -90,9 +91,9 @@ Custom Gas Token v2 was introduced in Upgrade 18 and is available in `op-contrac * **Flag alignment**: `isCustomGasToken` must match between L1 and L2 to prevent protocol violations * **Fee parameters**: `minBaseFee` and `operatorFee` must accurately account for execution and data availability costs in the native token's denomination -* **Decimal support**: CGT currently supports only 18-decimal tokens +* **Decimal support**: CGT currently supports only 18-decimal tokens. +ERC20s with different decimals require custom logic to handle rounding when converting between the token and the native asset. ## Next steps * **For chain operators**: See [Deploy a Custom Gas Token chain](/chain-operators/guides/features/custom-gas-token-guide) for detailed deployment instructions -* **Learn more**: Read the [full design specification](https://github.com/ethereum-optimism/design-docs/blob/main/protocol/custom-gas-token.md) for technical details From 1fd2cfd257cd83978c7c61e764a326c85d652ff3 Mon Sep 17 00:00:00 2001 From: soyboy Date: Mon, 15 Dec 2025 16:34:25 -0800 Subject: [PATCH 3/3] cleaning up the guide --- .../features/custom-gas-token-guide.mdx | 260 ++++-------------- 1 file changed, 59 insertions(+), 201 deletions(-) diff --git a/chain-operators/guides/features/custom-gas-token-guide.mdx b/chain-operators/guides/features/custom-gas-token-guide.mdx index e3beac1ad..e1b6b5fd9 100644 --- a/chain-operators/guides/features/custom-gas-token-guide.mdx +++ b/chain-operators/guides/features/custom-gas-token-guide.mdx @@ -31,24 +31,23 @@ Deploying a CGT chain follows the standard OP Stack deployment process with addi - Create a new intent file using OP Deployer's init command: + Create a new intent file using OP Deployer's [init command](/chain-operators/tools/op-deployer/usage/init): ```bash op-deployer init \ --l1-chain-id \ --l2-chain-ids \ - --outdir ./deployment \ - --intent-type standard + --intent-type custom ``` - This creates an `intent.toml` file in the `./deployment` directory. + This creates an `intent.toml` file. Open your `intent.toml` file and add the Custom Gas Token configuration. Below is an example with CGT-specific fields: ```toml - configType = "standard" + configType = "custom" l1ChainID = 11155111 fundDevAccounts = false useInterop = false @@ -56,23 +55,26 @@ Deploying a CGT chain follows the standard OP Stack deployment process with addi l2ContractsLocator = "tag://op-contracts/v6.0.0" [superchainRoles] - proxyAdminOwner = "0xYourMultisigAddress" - protocolVersionsOwner = "0xYourMultisigAddress" - guardian = "0xYourMultisigAddress" + SuperchainProxyAdminOwner = "0xYourMultisigAddress" + SuperchainGuardian = "0xYourMultisigAddress" + ProtocolVersionsOwner = "0xYourMultisigAddress" + Challenger = "0xYourMultisigAddress" [[chains]] id = "0x0000000000000000000000000000000000000000000000000000000000001234" - - # Fee vault recipients baseFeeVaultRecipient = "0xYourFeeRecipientAddress" l1FeeVaultRecipient = "0xYourFeeRecipientAddress" sequencerFeeVaultRecipient = "0xYourFeeRecipientAddress" operatorFeeVaultRecipient = "0xYourFeeRecipientAddress" - - # Standard EIP-1559 parameters - eip1559DenominatorCanyon = 250 - eip1559Denominator = 50 - eip1559Elasticity = 6 + eip1559DenominatorCanyon = 0 + eip1559Denominator = 0 + eip1559Elasticity = 0 + gasLimit = 60000000 + operatorFeeScalar = 0 + operatorFeeConstant = 0 + chainFeesRecipient = "0x0000000000000000000000000000000000000000" + minBaseFee = 0 + daFootprintGasScalar = 0 [chains.roles] l1ProxyAdminOwner = "0xYourMultisigAddress" @@ -96,7 +98,7 @@ Deploying a CGT chain follows the standard OP Stack deployment process with addi |-------|-------------|----------| | `customGasTokenName` | Name of the native asset (e.g., "My Custom Token") | Yes | | `customGasTokenSymbol` | Symbol for the native asset (e.g., "MCT") | Yes | - | `initialLiquiditySupply` | Initial supply minted to NativeAssetLiquidity at genesis | Yes | + | `initialLiquiditySupply` | Initial supply minted to NativeAssetLiquidity at genesis | No, default: type(uint248).max | | `liquidityControllerOwner` | Manages the asset supply | No, `L2ProxyAdminOwner` will be used as default | @@ -109,13 +111,12 @@ Deploying a CGT chain follows the standard OP Stack deployment process with addi - Deploy your L1 contracts using OP Deployer: + Deploy your L1 contracts using OP Deployer's [apply command](/chain-operators/tools/op-deployer/usage/apply) ```bash op-deployer apply \ --l1-rpc-url \ - --private-key \ - --workdir ./deployment + --private-key ``` This deploys all necessary L1 contracts including `SystemConfig` with the `isCustomGasToken` flag enabled, which instructs L1 contracts to reject ETH-value transactions. @@ -125,205 +126,62 @@ Deploying a CGT chain follows the standard OP Stack deployment process with addi - - After L1 deployment completes, initialize your L2 genesis: - - ```bash - # TODO: Add specific genesis initialization command for CGT chains - # This will create genesis.json with: - # - NativeAssetLiquidity predeploy at 0x4200000000000000000000000000000000000024 - # - LiquidityController predeploy at 0x4200000000000000000000000000000000000025 - # - Initial supply minted to NativeAssetLiquidity - # - L1Block configured with isCustomGasToken flag - ``` - - The genesis configuration automatically: - * Creates the `NativeAssetLiquidity` contract with your specified initial supply - * Deploys the `LiquidityController` with configured token metadata and owner. - * Sets the `isCustomGasToken` flag in `L1Block` to prevent ETH operations on L2 - * Configures fee parameters in `SystemConfig` + + Optionally you can use OP Deployer's [verify command](/chain-operators/tools/op-deployer/usage/verify) to verify your L1 contracts on Blockscout or Etherscan. - - After genesis initialization, configure the liquidity controller and authorize initial minters. You'll need to: - - **1. Verify deployment** - - Check that the predeploys are correctly configured: + + After L1 deployment completes, initialize your L2 genesis with OP Deployer's [apply command](/chain-operators/tools/op-deployer/usage/apply): ```bash - # TODO: Add commands to verify predeploy addresses and configuration - # Verify NativeAssetLiquidity has initial supply - # Verify LiquidityController has correct metadata - # Verify L1Block isCustomGasToken flag is true - ``` - - **2. Authorize initial minters** - - Grant minting permissions to your bridge or converter contracts: - - ```solidity - // Example: Authorize a bridge contract to mint native assets - // This is typically done by the ProxyAdmin owner - - // TODO: Provide specific authorization commands/scripts - // LiquidityController.authorizeMinter(bridgeAddress) + op-deployer apply \ + --deployment-target genesis ``` - - **Security critical**: Any address granted minting permissions can unlock native assets from the liquidity pool. Ensure all authorized minters are thoroughly audited and secured with appropriate access controls. - - - **3. Implement rate limiting (recommended)** - - Consider implementing rate limits on authorized minters to reduce risk: - - ```solidity - // TODO: Provide rate limiting implementation examples or references - ``` + The genesis configuration is applied based on your `initent.toml`. - Start your OP Stack services with CGT-aware configuration: + Start your OP Stack services to start sequencing your CGT chain: - **op-geth** - - ```bash - # TODO: Add CGT-specific op-geth configuration if needed - # Standard op-geth configuration should work - ``` - - **op-node** - - ```bash - # TODO: Add CGT-specific op-node configuration - # Rollup config must have isCustomGasToken flag set - ``` - - **op-batcher** - - ```bash - # TODO: Add CGT-specific batcher configuration - # Standard batcher configuration should work - ``` - - **op-proposer** - - ```bash - # TODO: Add CGT-specific proposer configuration - # Standard proposer configuration should work - ``` + * Sequencer Execution Client + * Sequencer Consensus Client + * Batcher + * Proposer + * Challenger Your rollup configuration file must include `"isCustomGasToken": true` to ensure all services correctly handle CGT mode. - - Deploy your application-layer bridge or converter contracts. The specific implementation depends on your use case: - - ### Option A: L1 ERC-20 bridging - - If you're bridging an existing L1 ERC-20 token: - - ```mermaid - sequenceDiagram - participant User - participant L1Bridge - participant L1Messenger - participant L2Bridge - participant LiquidityController - participant NativeAssetLiquidity - - User->>L1Bridge: Deposit ERC-20 - L1Bridge->>L1Bridge: Lock/Burn ERC-20 - L1Bridge->>L1Messenger: Send message - L1Messenger->>L2Bridge: Relay message - L2Bridge->>LiquidityController: mint() - LiquidityController->>NativeAssetLiquidity: withdraw() - NativeAssetLiquidity->>User: Native assets - ``` - - **1. Deploy L1 bridge contract** - - ```bash - # TODO: Provide L1 bridge deployment commands/scripts - # Bridge must be authorized as minter on L2 - ``` - - **2. Deploy L2 bridge contract** - - ```bash - # TODO: Provide L2 bridge deployment commands/scripts - # Must be authorized by LiquidityController - ``` - - **3. Authorize bridge as minter** - - ```bash - # TODO: Provide authorization commands - # LiquidityController.authorizeMinter(l2BridgeAddress) - ``` - - ### Option B: L2-native token - - If you're creating an L2-native asset with no L1 equivalent: - - ```bash - # TODO: Provide configuration for L2-native tokens - # Define initial distribution mechanism - # Configure authorized minters (DEX, rewards contract, etc.) - ``` - - ### Option C: Custom converter - - For advanced use cases with custom conversion logic: - - ```bash - # TODO: Provide custom converter implementation guidance - # Reference template contracts (when available) - ``` - - - **Templates coming soon**: The OP Stack team is developing standard bridge and converter templates to simplify integration. Check back for updates. - - - - Before going live, thoroughly test your CGT chain: - - **1. Verify flag alignment** - - ```bash - # Check L1 SystemConfig.isCustomGasToken() returns true - # Check L2 L1Block.isCustomGasToken() returns true - # Verify both flags match - ``` - - **2. Test native asset operations** - - ```bash - # Test minting native assets via authorized minter - # Test burning native assets - # Test fee payments in native token - # Verify fee vault accumulation - ``` - - **3. Test ETH rejection** - - ```bash - # Attempt ETH deposit via OptimismPortal (should fail) - # Attempt ETH withdrawal via L2ToL1MessagePasser (should fail) - # Verify ETH operations are properly blocked - ``` - - **4. Test bridge functionality** - - ```bash - # Test deposits (L1 → L2 native asset minting) - # Test withdrawals (L2 native → L1 token) - # Verify proper locking/unlocking in liquidity contract - ``` + Before going live, thoroughly test your CGT chain. The following are some key areas to check: + + **Verify flag alignment** + * Check L1 SystemConfig.isCustomGasToken() returns true + * Check L2 L1Block.isCustomGasToken() returns true + * Verify both flags match + + **Test native asset operations** + * Test minting native assets via authorized minter + * Test burning native assets + * Test fee payments in native token + * Verify fee vault accumulation + + + **Test ETH rejection** + * Attempt ETH deposit via OptimismPortal (should fail) + * Attempt ETH withdrawal via L2ToL1MessagePasser (should fail) + * Verify ETH operations are properly blocked + + + **Test bridge functionality** + + * Test deposits (L1 → L2 native asset minting) + * Test withdrawals (L2 native → L1 token) + * Verify proper locking/unlocking in liquidity contract +