Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions op-node/rollup/chain_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,18 @@ const maxSequencerDriftFjord = 1800
type ForkName string

const (
Bedrock ForkName = "bedrock"
Regolith ForkName = "regolith"
Canyon ForkName = "canyon"
Delta ForkName = "delta"
Ecotone ForkName = "ecotone"
Fjord ForkName = "fjord"
Granite ForkName = "granite"
Holocene ForkName = "holocene"
Isthmus ForkName = "isthmus"
Jovian ForkName = "jovian"
Interop ForkName = "interop"
Bedrock ForkName = "bedrock"
Regolith ForkName = "regolith"
Canyon ForkName = "canyon"
Delta ForkName = "delta"
Ecotone ForkName = "ecotone"
Fjord ForkName = "fjord"
Granite ForkName = "granite"
Holocene ForkName = "holocene"
Isthmus ForkName = "isthmus"
Jovian ForkName = "jovian"
Interop ForkName = "interop"
CustomGasToken ForkName = "custom_gas_token"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not exactly sure how to feature flag the best way, this cgt fork should be temporary

// ADD NEW FORKS TO AllForks BELOW!
None ForkName = ""
)
Expand All @@ -60,6 +61,7 @@ var AllForks = []ForkName{
Isthmus,
Jovian,
Interop,
CustomGasToken,
// ADD NEW FORKS HERE!
}

Expand Down
8 changes: 8 additions & 0 deletions op-node/rollup/derive/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ func (ba *FetchingAttributesBuilder) PreparePayloadAttributes(ctx context.Contex
}
}

if ba.rollupCfg.IsCustomGasToken(nextL2Time) {
customGasToken, err := CustomGasTokenNetworkUpgradeTransactions()
if err != nil {
return nil, NewCriticalError(fmt.Errorf("failed to build custom gas token network upgrade txs: %w", err))
}
upgradeTxs = append(upgradeTxs, customGasToken...)
}

l1InfoTx, err := L1InfoDepositBytes(ba.rollupCfg, sysConfig, seqNumber, l1Info, nextL2Time)
if err != nil {
return nil, NewCriticalError(fmt.Errorf("failed to create l1InfoTx: %w", err))
Expand Down
14 changes: 14 additions & 0 deletions op-node/rollup/derive/custom_gas_token_upgrade_transactions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package derive

import (
"github.com/ethereum/go-ethereum/common/hexutil"
)

// CustomGasTokenNetworkUpgradeTransactions returns the transactions required to upgrade to use a custom gas token.
// For now, this function returns an empty slice of transactions as requested.
func CustomGasTokenNetworkUpgradeTransactions() ([]hexutil.Bytes, error) {
// TODO: Implement custom gas token upgrade transactions
// Deploy controller, liquidity, set implementations, mint ETH to liquidity
upgradeTxns := make([]hexutil.Bytes, 0)
return upgradeTxns, nil
}
Comment on lines +9 to +14
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High severity: Incomplete Custom Gas Token Upgrade Implementation

Description:
The CustomGasTokenNetworkUpgradeTransactions function returns empty upgrade transactions while the system activates custom gas token functionality. This creates a state where the rollup believes custom gas token is active but no actual deployment or configuration transactions are executed.

Recommendation:
Complete the implementation of CustomGasTokenNetworkUpgradeTransactions to include all necessary deployment and configuration transactions before enabling the custom gas token feature in production.

The fix requires a more nuanced change than an inline suggestion. Fixes via PR are coming soon!


Don't like this finding? Reply "dismiss" and it won't appear again in future scans.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package derive

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestCustomGasTokenNetworkTransactions(t *testing.T) {
upgradeTxns, err := CustomGasTokenNetworkUpgradeTransactions()
require.NoError(t, err)
// For now, the function returns an empty slice as requested
require.Len(t, upgradeTxns, 0)
}
40 changes: 40 additions & 0 deletions op-node/rollup/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ type Config struct {
// Active if InteropTime != nil && L2 block timestamp >= *InteropTime, inactive otherwise.
InteropTime *uint64 `json:"interop_time,omitempty"`

// CustomGasTokenTime sets the activation time of the Custom Gas Token network upgrade.
// Active if CustomGasTokenTime != nil && L2 block timestamp >= *CustomGasTokenTime, inactive otherwise.
// TODO: replace with custom gas token fork name
CustomGasTokenTime *uint64 `json:"custom_gas_token_time,omitempty"`

// Note: below addresses are part of the block-derivation process,
// and required to be the same network-wide to stay in consensus.

Expand Down Expand Up @@ -162,6 +167,14 @@ type Config struct {
// This feature (de)activates by L1 origin timestamp, to keep a consistent L1 block info per L2
// epoch.
PectraBlobScheduleTime *uint64 `json:"pectra_blob_schedule_time,omitempty"`

// Custom Gas Token Configuration
// IsCustomGasToken indicates whether this chain uses a custom gas token instead of ETH
CustomGasToken bool `json:"is_custom_gas_token,omitempty"`
// GasTokenName is the name of the custom gas token
GasTokenName string `json:"gas_token_name,omitempty"`
// GasTokenSymbol is the symbol of the custom gas token
GasTokenSymbol string `json:"gas_token_symbol,omitempty"`
}

// ValidateL1Config checks L1 config variables for errors.
Expand Down Expand Up @@ -470,6 +483,12 @@ func (c *Config) IsJovian(timestamp uint64) bool {
return c.JovianTime != nil && timestamp >= *c.JovianTime
}

// TODO: use correct name
// IsCustomGasToken returns true if the Custom Gas Token hardfork is active at or past the given timestamp.
func (c *Config) IsCustomGasToken(timestamp uint64) bool {
return c.CustomGasToken && c.CustomGasTokenTime != nil && timestamp >= *c.CustomGasTokenTime
}

// IsInterop returns true if the Interop hardfork is active at or past the given timestamp.
func (c *Config) IsInterop(timestamp uint64) bool {
return c.InteropTime != nil && timestamp >= *c.InteropTime
Expand Down Expand Up @@ -547,6 +566,14 @@ func (c *Config) IsInteropActivationBlock(l2BlockTime uint64) bool {
!c.IsInterop(l2BlockTime-c.BlockTime)
}

// IsCustomGasTokenActivationBlock returns whether the specified block is the first block subject to the
// Custom Gas Token upgrade.
func (c *Config) IsCustomGasTokenActivationBlock(l2BlockTime uint64) bool {
return c.IsCustomGasToken(l2BlockTime) &&
l2BlockTime >= c.BlockTime &&
!c.IsCustomGasToken(l2BlockTime-c.BlockTime)
}

// IsActivationBlock returns the fork which activates at the block with time newTime if the previous
// block's time is oldTime. It return an empty ForkName if no fork activation takes place between
// those timestamps. It can be used for both, L1 and L2 blocks.
Expand All @@ -555,6 +582,9 @@ func (c *Config) IsActivationBlock(oldTime, newTime uint64) ForkName {
if c.IsInterop(newTime) && !c.IsInterop(oldTime) {
return Interop
}
if c.IsCustomGasToken(newTime) && !c.IsCustomGasToken(oldTime) {
return CustomGasToken
}
if c.IsIsthmus(newTime) && !c.IsIsthmus(oldTime) {
return Isthmus
}
Expand Down Expand Up @@ -586,6 +616,9 @@ func (c *Config) IsActivationBlockForFork(l2BlockTime uint64, forkName ForkName)
func (c *Config) ActivateAtGenesis(hardfork ForkName) {
// IMPORTANT! ordered from newest to oldest
switch hardfork {
case CustomGasToken:
c.CustomGasTokenTime = new(uint64)
fallthrough
case Jovian:
c.JovianTime = new(uint64)
fallthrough
Expand Down Expand Up @@ -739,6 +772,9 @@ func (c *Config) Description(l2Chains map[string]string) string {
if c.AltDAConfig != nil {
banner += fmt.Sprintf("Node supports Alt-DA Mode with CommitmentType %v\n", c.AltDAConfig.CommitmentType)
}
if c.CustomGasToken {
banner += fmt.Sprintf("Node supports Custom Gas Token: %s (%s)\n", c.GasTokenName, c.GasTokenSymbol)
}
return banner
}

Expand Down Expand Up @@ -776,6 +812,9 @@ func (c *Config) LogDescription(log log.Logger, l2Chains map[string]string) {
if c.AltDAConfig != nil {
ctx = append(ctx, "alt_da", *c.AltDAConfig)
}
if c.CustomGasToken {
ctx = append(ctx, "custom_gas_token", true, "gas_token_name", c.GasTokenName, "gas_token_symbol", c.GasTokenSymbol)
}
log.Info("Rollup Config", ctx...)
}

Expand All @@ -794,6 +833,7 @@ func (c *Config) forEachFork(callback func(name string, logName string, time *ui
callback("Isthmus", "isthmus_time", c.IsthmusTime)
callback("Jovian", "jovian_time", c.JovianTime)
callback("Interop", "interop_time", c.InteropTime)
callback("Custom Gas Token", "custom_gas_token_time", c.CustomGasTokenTime)
}

func (c *Config) ParseRollupConfig(in io.Reader) error {
Expand Down
30 changes: 30 additions & 0 deletions op-node/rollup/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -919,3 +919,33 @@ func TestConfig_ProbablyMissingPectraBlobSchedule(t *testing.T) {
})
}
}

func TestConfig_CustomGasToken(t *testing.T) {
activationTime := uint64(1002) // First block after genesis
cfg := &Config{
BlockTime: 2,
CustomGasToken: true,
CustomGasTokenTime: &activationTime,
GasTokenName: "Test Token",
GasTokenSymbol: "TEST",
}

// Test IsCustomGasTokenActivationBlock
// Should return true for the first block after genesis when custom gas token is enabled
genesisTime := uint64(1000)
firstBlockTime := genesisTime + cfg.BlockTime

// First block should be activation block
require.True(t, cfg.IsCustomGasTokenActivationBlock(firstBlockTime))

// Second block should not be activation block
secondBlockTime := firstBlockTime + cfg.BlockTime
require.False(t, cfg.IsCustomGasTokenActivationBlock(secondBlockTime))

// Test with custom gas token disabled
cfgDisabled := &Config{
BlockTime: 2,
CustomGasToken: false,
}
require.False(t, cfgDisabled.IsCustomGasTokenActivationBlock(firstBlockTime))
}