diff --git a/op-chain-ops/genesis/config.go b/op-chain-ops/genesis/config.go index ad399f7da88..872b2fad701 100644 --- a/op-chain-ops/genesis/config.go +++ b/op-chain-ops/genesis/config.go @@ -296,6 +296,8 @@ func (d *GasTokenDeployConfig) Check(log log.Logger) error { if d.NativeAssetLiquidityAmount == nil { return fmt.Errorf("%w: NativeAssetLiquidityAmount cannot be nil", ErrInvalidDeployConfig) } + + log.Info("Using custom gas token", "name", d.GasPayingTokenName, "symbol", d.GasPayingTokenSymbol, "nativeAssetLiquidityAmount", d.NativeAssetLiquidityAmount.ToInt()) } return nil } diff --git a/op-deployer/pkg/deployer/pipeline/l2genesis.go b/op-deployer/pkg/deployer/pipeline/l2genesis.go index 7088a8ec9e2..f2f312dc0a6 100644 --- a/op-deployer/pkg/deployer/pipeline/l2genesis.go +++ b/op-deployer/pkg/deployer/pipeline/l2genesis.go @@ -22,9 +22,13 @@ import ( ) type l2GenesisOverrides struct { - UseCustomGasToken bool `json:"useCustomGasToken"` - GasPayingTokenName string `json:"gasPayingTokenName"` - GasPayingTokenSymbol string `json:"gasPayingTokenSymbol"` + // ===== CUSTOM GAS TOKEN (CGT) CONFIGURATION ===== + UseCustomGasToken bool `json:"useCustomGasToken"` // CGT: Enable custom gas token mode + GasPayingTokenName string `json:"gasPayingTokenName"` // CGT: Name of the custom gas token + GasPayingTokenSymbol string `json:"gasPayingTokenSymbol"` // CGT: Symbol of the custom gas token + NativeAssetLiquidityAmount *hexutil.Big `json:"nativeAssetLiquidityAmount"` // CGT: Liquidity amount for NativeAssetLiquidity contract + + // ===== GENERAL L2 CONFIGURATION (NON-CGT) ===== FundDevAccounts bool `json:"fundDevAccounts"` BaseFeeVaultMinimumWithdrawalAmount *hexutil.Big `json:"baseFeeVaultMinimumWithdrawalAmount"` L1FeeVaultMinimumWithdrawalAmount *hexutil.Big `json:"l1FeeVaultMinimumWithdrawalAmount"` @@ -34,7 +38,6 @@ type l2GenesisOverrides struct { SequencerFeeVaultWithdrawalNetwork genesis.WithdrawalNetwork `json:"sequencerFeeVaultWithdrawalNetwork"` EnableGovernance bool `json:"enableGovernance"` GovernanceTokenOwner common.Address `json:"governanceTokenOwner"` - NativeAssetLiquidityAmount *hexutil.Big `json:"nativeAssetLiquidityAmount"` } func GenerateL2Genesis(pEnv *Env, intent *state.Intent, bundle ArtifactsBundle, st *state.State, chainID common.Hash) error { @@ -98,10 +101,11 @@ func GenerateL2Genesis(pEnv *Env, intent *state.Intent, bundle ArtifactsBundle, DeployCrossL2Inbox: len(intent.Chains) > 1, EnableGovernance: overrides.EnableGovernance, FundDevAccounts: overrides.FundDevAccounts, - UseCustomGasToken: thisIntent.CustomGasToken.Enabled, - GasPayingTokenName: thisIntent.CustomGasToken.Name, - GasPayingTokenSymbol: thisIntent.CustomGasToken.Symbol, - NativeAssetLiquidityAmount: thisIntent.GetNativeAssetLiquidityAmount(), + // Custom Gas Token (CGT) configuration passed to L2Genesis script + UseCustomGasToken: thisIntent.CustomGasToken.Enabled, // CGT: Enable/disable custom gas token + GasPayingTokenName: thisIntent.CustomGasToken.Name, // CGT: Token name (e.g., "Custom Gas Token") + GasPayingTokenSymbol: thisIntent.CustomGasToken.Symbol, // CGT: Token symbol (e.g., "CGT") + NativeAssetLiquidityAmount: thisIntent.CustomGasToken.NativeAssetLiquidityAmount.ToInt(), // CGT: Liquidity amount for NativeAssetLiquidity contract }); err != nil { return fmt.Errorf("failed to call L2Genesis script: %w", err) } @@ -172,13 +176,8 @@ func wdNetworkToBig(wd genesis.WithdrawalNetwork) *big.Int { } func defaultOverrides() l2GenesisOverrides { - // Default to type(uint248).max = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - maxUint248, _ := new(big.Int).SetString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16) - return l2GenesisOverrides{ - UseCustomGasToken: false, - GasPayingTokenName: "", - GasPayingTokenSymbol: "", + // ===== GENERAL L2 DEFAULTS ===== FundDevAccounts: false, BaseFeeVaultMinimumWithdrawalAmount: standard.VaultMinWithdrawalAmount, L1FeeVaultMinimumWithdrawalAmount: standard.VaultMinWithdrawalAmount, @@ -188,6 +187,10 @@ func defaultOverrides() l2GenesisOverrides { SequencerFeeVaultWithdrawalNetwork: "local", EnableGovernance: false, GovernanceTokenOwner: standard.GovernanceTokenOwner, - NativeAssetLiquidityAmount: (*hexutil.Big)(maxUint248), + // ===== CGT DEFAULTS ===== + UseCustomGasToken: false, // CGT disabled by default + GasPayingTokenName: "", // Empty when CGT disabled + GasPayingTokenSymbol: "", // Empty when CGT disabled + NativeAssetLiquidityAmount: (*hexutil.Big)(big.NewInt(0)), // Default to 0 when CGT disabled (consistent with "" and false) } } diff --git a/op-deployer/pkg/deployer/pipeline/l2genesis_test.go b/op-deployer/pkg/deployer/pipeline/l2genesis_test.go index 48e09f15231..65bcf4860cb 100644 --- a/op-deployer/pkg/deployer/pipeline/l2genesis_test.go +++ b/op-deployer/pkg/deployer/pipeline/l2genesis_test.go @@ -70,6 +70,7 @@ func TestCalculateL2GenesisOverrides(t *testing.T) { "useCustomGasToken": false, "gasPayingTokenName": "", "gasPayingTokenSymbol": "", + "nativeAssetLiquidityAmount": "0x0", }, }, chainIntent: &state.ChainIntent{}, @@ -85,6 +86,7 @@ func TestCalculateL2GenesisOverrides(t *testing.T) { defaults.SequencerFeeVaultWithdrawalNetwork = "remote" defaults.EnableGovernance = true defaults.GovernanceTokenOwner = common.HexToAddress("0x1111111111111111111111111111111111111111") + defaults.NativeAssetLiquidityAmount = (*hexutil.Big)(hexutil.MustDecodeBig("0x0")) return defaults }(), expectedSchedule: func() *genesis.UpgradeScheduleDeployConfig { @@ -116,6 +118,7 @@ func TestCalculateL2GenesisOverrides(t *testing.T) { "useCustomGasToken": false, "gasPayingTokenName": "", "gasPayingTokenSymbol": "", + "nativeAssetLiquidityAmount": "0x0", }, }, expectError: false, @@ -130,6 +133,7 @@ func TestCalculateL2GenesisOverrides(t *testing.T) { defaults.SequencerFeeVaultWithdrawalNetwork = "remote" defaults.EnableGovernance = true defaults.GovernanceTokenOwner = common.HexToAddress("0x1111111111111111111111111111111111111111") + defaults.NativeAssetLiquidityAmount = (*hexutil.Big)(hexutil.MustDecodeBig("0x0")) return defaults }(), expectedSchedule: func() *genesis.UpgradeScheduleDeployConfig { @@ -144,11 +148,17 @@ func TestCalculateL2GenesisOverrides(t *testing.T) { L1ContractsLocator: &artifacts.Locator{}, GlobalDeployOverrides: map[string]any{ "l2GenesisInteropTimeOffset": "0x0", + "nativeAssetLiquidityAmount": "0x0", }, }, - chainIntent: &state.ChainIntent{}, - expectError: false, - expectedOverrides: defaultOverrides(), + chainIntent: &state.ChainIntent{}, + expectError: false, + expectedOverrides: func() l2GenesisOverrides { + defaults := defaultOverrides() + // Override with the same value that comes from JSON merge to match internal representation + defaults.NativeAssetLiquidityAmount = (*hexutil.Big)(hexutil.MustDecodeBig("0x0")) + return defaults + }(), expectedSchedule: func() *genesis.UpgradeScheduleDeployConfig { schedule := standard.DefaultHardforkScheduleForTag("") schedule.L2GenesisInteropTimeOffset = op_service.U64UtilPtr(0) diff --git a/op-deployer/pkg/deployer/state/chain_intent.go b/op-deployer/pkg/deployer/state/chain_intent.go index 60f953ebb0a..71497dfed38 100644 --- a/op-deployer/pkg/deployer/state/chain_intent.go +++ b/op-deployer/pkg/deployer/state/chain_intent.go @@ -2,7 +2,6 @@ package state import ( "fmt" - "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -134,6 +133,10 @@ func (c *ChainIntent) Check() error { if c.CustomGasToken.Symbol == "" { return fmt.Errorf("%w: CustomGasToken.Symbol cannot be empty when enabled, chainId=%s", ErrIncompatibleValue, c.ID) } + + if c.CustomGasToken.NativeAssetLiquidityAmount == nil { + return fmt.Errorf("%w: CustomGasToken.NativeAssetLiquidityAmount must be set when custom gas token is enabled, chainId=%s", ErrIncompatibleValue, c.ID) + } } if c.DangerousAltDAConfig.UseAltDA { @@ -142,14 +145,3 @@ func (c *ChainIntent) Check() error { return nil } - -// GetNativeAssetLiquidityAmount returns the native asset liquidity amount for the chain. -// If not set, returns the default value of type(uint248).max. -func (c *ChainIntent) GetNativeAssetLiquidityAmount() *big.Int { - if c.CustomGasToken != nil && c.CustomGasToken.NativeAssetLiquidityAmount != nil { - return c.CustomGasToken.NativeAssetLiquidityAmount.ToInt() - } - // Default to type(uint248).max = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - maxUint248, _ := new(big.Int).SetString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16) - return maxUint248 -} diff --git a/op-deployer/pkg/deployer/state/intent.go b/op-deployer/pkg/deployer/state/intent.go index ebeaf0d395a..8879e5df237 100644 --- a/op-deployer/pkg/deployer/state/intent.go +++ b/op-deployer/pkg/deployer/state/intent.go @@ -158,6 +158,10 @@ func (c *Intent) validateStandardValues() error { if len(chain.AdditionalDisputeGames) > 0 { return fmt.Errorf("%w: chainId=%s additionalDisputeGames must be nil", ErrNonStandardValue, chain.ID) } + + if chain.CustomGasToken != nil { + return fmt.Errorf("%w: chainId=%s custom gas token must be nil for standard chains", ErrNonStandardValue, chain.ID) + } } challenger, _ := standard.ChallengerAddressFor(c.L1ChainID) @@ -349,12 +353,7 @@ func NewIntentStandard(l1ChainId uint64, l2ChainIds []common.Hash) (Intent, erro L1ProxyAdminOwner: l1ProxyAdminOwner, L2ProxyAdminOwner: l2ProxyAdminOwner, }, - CustomGasToken: &CustomGasToken{ - Enabled: false, - Name: "", - Symbol: "", - NativeAssetLiquidityAmount: nil, - }, + CustomGasToken: nil, // Standard chains must have nil CustomGasToken }) } return intent, nil diff --git a/op-deployer/pkg/deployer/state/intent_test.go b/op-deployer/pkg/deployer/state/intent_test.go index fc220552914..9507054f575 100644 --- a/op-deployer/pkg/deployer/state/intent_test.go +++ b/op-deployer/pkg/deployer/state/intent_test.go @@ -1,10 +1,12 @@ package state import ( + "math/big" "testing" "github.com/ethereum-optimism/optimism/op-chain-ops/addresses" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/require" ) @@ -62,6 +64,18 @@ func TestValidateStandardValues(t *testing.T) { }, ErrNonStandardValue, }, + { + "CustomGasToken", + func(intent *Intent) { + intent.Chains[0].CustomGasToken = &CustomGasToken{ + Enabled: false, + Name: "", + Symbol: "", + NativeAssetLiquidityAmount: (*hexutil.Big)(big.NewInt(0)), + } + }, + ErrNonStandardValue, + }, { "SuperchainConfigProxy", func(intent *Intent) { @@ -239,9 +253,14 @@ func setFeeAddresses(intent *Intent) { } func setCustomGasToken(intent *Intent) { + // 1000 ETH in wei (1000 * 10^18) + amount := new(big.Int) + amount.SetString("1000000000000000000000", 10) + intent.Chains[0].CustomGasToken = &CustomGasToken{ - Enabled: true, - Name: "Custom Gas Token", - Symbol: "CGT", + Enabled: true, + Name: "Custom Gas Token", + Symbol: "CGT", + NativeAssetLiquidityAmount: (*hexutil.Big)(amount), } } diff --git a/op-devstack/sysgo/deployer.go b/op-devstack/sysgo/deployer.go index 98679e26508..c017ac4be92 100644 --- a/op-devstack/sysgo/deployer.go +++ b/op-devstack/sysgo/deployer.go @@ -339,10 +339,10 @@ func WithDisputeGameFinalityDelaySeconds(seconds uint64) DeployerOption { } } -func WithCustomGasToken(enabled bool, name, symbol string) DeployerOption { +func WithCustomGasToken(enabled bool, name, symbol string, nativeAssetLiquidityAmount *big.Int) DeployerOption { return func(p devtest.P, keys devkeys.Keys, builder intentbuilder.Builder) { for _, l2Cfg := range builder.L2s() { - l2Cfg.WithCustomGasToken(enabled, name, symbol) + l2Cfg.WithCustomGasToken(enabled, name, symbol, nativeAssetLiquidityAmount) } } } diff --git a/op-e2e/config/init.go b/op-e2e/config/init.go index 495831488cb..37dcc27da3b 100644 --- a/op-e2e/config/init.go +++ b/op-e2e/config/init.go @@ -401,9 +401,10 @@ func defaultIntent(root string, loc *artifacts.Locator, deployer common.Address, Challenger: common.HexToAddress("0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65"), }, CustomGasToken: &state.CustomGasToken{ - Enabled: false, - Name: "", - Symbol: "", + Enabled: false, + Name: "", + Symbol: "", + NativeAssetLiquidityAmount: nil, }, AdditionalDisputeGames: []state.AdditionalDisputeGame{ { diff --git a/op-e2e/e2eutils/intentbuilder/builder.go b/op-e2e/e2eutils/intentbuilder/builder.go index b75d25fc9a3..47daff25d82 100644 --- a/op-e2e/e2eutils/intentbuilder/builder.go +++ b/op-e2e/e2eutils/intentbuilder/builder.go @@ -2,6 +2,7 @@ package intentbuilder import ( "fmt" + "math/big" "github.com/holiman/uint256" "github.com/stretchr/testify/require" @@ -48,7 +49,7 @@ type L2Configurator interface { WithL1StartBlockHash(hash common.Hash) WithAdditionalDisputeGames(games []state.AdditionalDisputeGame) WithFinalizationPeriodSeconds(value uint64) - WithCustomGasToken(enabled bool, name, symbol string) + WithCustomGasToken(enabled bool, name string, symbol string, nativeAssetLiquidityAmount *big.Int) ContractsConfigurator L2VaultsConfigurator L2RolesConfigurator @@ -388,11 +389,12 @@ func (c *l2Configurator) WithEIP1559Denominator(value uint64) { c.builder.intent.Chains[c.chainIndex].Eip1559Denominator = value } -func (c *l2Configurator) WithCustomGasToken(enabled bool, name, symbol string) { +func (c *l2Configurator) WithCustomGasToken(enabled bool, name, symbol string, nativeAssetLiquidityAmount *big.Int) { c.builder.intent.Chains[c.chainIndex].CustomGasToken = &state.CustomGasToken{ - Enabled: enabled, - Name: name, - Symbol: symbol, + Enabled: enabled, + Name: name, + Symbol: symbol, + NativeAssetLiquidityAmount: (*hexutil.Big)(nativeAssetLiquidityAmount), } } diff --git a/op-e2e/e2eutils/intentbuilder/builder_test.go b/op-e2e/e2eutils/intentbuilder/builder_test.go index c2b40da9b83..15b50d83f5f 100644 --- a/op-e2e/e2eutils/intentbuilder/builder_test.go +++ b/op-e2e/e2eutils/intentbuilder/builder_test.go @@ -2,6 +2,7 @@ package intentbuilder import ( "encoding/json" + "math/big" "net/url" "testing" @@ -69,7 +70,7 @@ func TestBuilder(t *testing.T) { require.Equal(t, eth.ChainIDFromUInt64(420), l2Config.ChainID()) l2Config.WithBlockTime(2) l2Config.WithL1StartBlockHash(common.HexToHash("0x5678")) - l2Config.WithCustomGasToken(false, "", "") + l2Config.WithCustomGasToken(false, "", "", (*big.Int)(big.NewInt(0))) // Test ContractsConfigurator methods l2Config.WithL1ContractsLocator("http://l1.example.com") @@ -163,9 +164,10 @@ func TestBuilder(t *testing.T) { OperatorFeeScalar: 100, OperatorFeeConstant: 200, CustomGasToken: &state.CustomGasToken{ - Enabled: false, - Name: "", - Symbol: "", + Enabled: false, + Name: "", + Symbol: "", + NativeAssetLiquidityAmount: (*hexutil.Big)(big.NewInt(0)), }, DeployOverrides: map[string]any{ "l2BlockTime": uint64(2), diff --git a/packages/contracts-bedrock/deploy-config/hardhat.json b/packages/contracts-bedrock/deploy-config/hardhat.json index e85334e7677..d330d134595 100644 --- a/packages/contracts-bedrock/deploy-config/hardhat.json +++ b/packages/contracts-bedrock/deploy-config/hardhat.json @@ -65,5 +65,6 @@ "daResolverRefundPercentage": 50, "useCustomGasToken": false, "gasPayingTokenName": "", - "gasPayingTokenSymbol": "" + "gasPayingTokenSymbol": "", + "nativeAssetLiquidityAmount": null } diff --git a/packages/contracts-bedrock/deploy-config/internal-devnet.json b/packages/contracts-bedrock/deploy-config/internal-devnet.json index 6e862b3bdff..e74050bb76c 100644 --- a/packages/contracts-bedrock/deploy-config/internal-devnet.json +++ b/packages/contracts-bedrock/deploy-config/internal-devnet.json @@ -41,5 +41,6 @@ "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", "useCustomGasToken": false, "gasPayingTokenName": "", - "gasPayingTokenSymbol": "" + "gasPayingTokenSymbol": "", + "nativeAssetLiquidityAmount": null } diff --git a/packages/contracts-bedrock/deploy-config/mainnet.json b/packages/contracts-bedrock/deploy-config/mainnet.json index 9f1888f7c89..ae9b04ec3a4 100644 --- a/packages/contracts-bedrock/deploy-config/mainnet.json +++ b/packages/contracts-bedrock/deploy-config/mainnet.json @@ -58,5 +58,6 @@ "useFaultProofs": true, "useCustomGasToken": false, "gasPayingTokenName": "", - "gasPayingTokenSymbol": "" + "gasPayingTokenSymbol": "", + "nativeAssetLiquidityAmount": null } diff --git a/packages/contracts-bedrock/deploy-config/sepolia-devnet-0.json b/packages/contracts-bedrock/deploy-config/sepolia-devnet-0.json index fd698f334e4..78575879084 100644 --- a/packages/contracts-bedrock/deploy-config/sepolia-devnet-0.json +++ b/packages/contracts-bedrock/deploy-config/sepolia-devnet-0.json @@ -82,5 +82,6 @@ "recommendedProtocolVersion": "0x0000000000000000000000000000000000000005000000000000000000000000", "useCustomGasToken": false, "gasPayingTokenName": "", - "gasPayingTokenSymbol": "" + "gasPayingTokenSymbol": "", + "nativeAssetLiquidityAmount": null } diff --git a/packages/contracts-bedrock/deploy-config/sepolia.json b/packages/contracts-bedrock/deploy-config/sepolia.json index 87db17dbda2..22ad35b1480 100644 --- a/packages/contracts-bedrock/deploy-config/sepolia.json +++ b/packages/contracts-bedrock/deploy-config/sepolia.json @@ -57,5 +57,6 @@ "useFaultProofs": true, "useCustomGasToken": false, "gasPayingTokenName": "", - "gasPayingTokenSymbol": "" + "gasPayingTokenSymbol": "", + "nativeAssetLiquidityAmount": null } diff --git a/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol index b8eac8177e2..9db32e7c5b9 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol @@ -111,7 +111,7 @@ contract DeployOPChainInput is BaseDeployIO { if (_sel == this.disputeAbsolutePrestate.selector) { _disputeAbsolutePrestate = Claim.wrap(_value); } else { - revert("DeployImplementationsInput: unknown selector"); + revert("DeployOPChainInput: unknown selector"); } }