Repository: mantlenetworkio/mantle (language: go)

Issue:
[l2geth]: Upgrade l2geth, including hard fork upgrades and precompiled contract upgrades
**Description**
To upgrade l2geth, including hard fork upgrades and precompiled contract upgrades.

**Requirements**

- design a framework to manage upgrades for different networks(mainet, testnet an so on) including upgrade configuration management.
- estimate upgrade time accurately. Use Layer1 block number or Layer2 block number to set upgrade timing
- consolidate and organize existing upgrades, including eignlyer upgrade, tss reward upgrade and mantle token upgrade


Discussion / hints:

Fix patch:
diff --git a/fraud-proof/proof/api.go b/fraud-proof/proof/api.go
index 59fcda114..0d1014eb7 100644
--- a/fraud-proof/proof/api.go
+++ b/fraud-proof/proof/api.go
@@ -66,6 +66,10 @@ type chainContext struct {
 	ctx     context.Context
 }
 
+func (context *chainContext) ChainDb() ethdb.Database {
+	panic("not implemented")
+}
+
 func (context *chainContext) Engine() consensus.Engine {
 	return context.backend.Engine()
 }
diff --git a/l2geth/cmd/geth/main.go b/l2geth/cmd/geth/main.go
index bba922df6..9be0f3870 100644
--- a/l2geth/cmd/geth/main.go
+++ b/l2geth/cmd/geth/main.go
@@ -159,7 +159,6 @@ var (
 		utils.RollupClientHttpFlag,
 		utils.RollupEnableVerifierFlag,
 		utils.RollupMpcVerifierFlag,
-		utils.RollupEigenDaBlockFlag,
 		utils.RollupTimstampRefreshFlag,
 		utils.RollupPollIntervalFlag,
 		utils.RollupMaxCalldataSizeFlag,
diff --git a/l2geth/cmd/geth/usage.go b/l2geth/cmd/geth/usage.go
index 970a57554..6abb3545a 100644
--- a/l2geth/cmd/geth/usage.go
+++ b/l2geth/cmd/geth/usage.go
@@ -71,7 +71,6 @@ var AppHelpFlagGroups = []flagGroup{
 			utils.RollupClientHttpFlag,
 			utils.RollupEnableVerifierFlag,
 			utils.RollupMpcVerifierFlag,
-			utils.RollupEigenDaBlockFlag,
 			utils.RollupTimstampRefreshFlag,
 			utils.RollupPollIntervalFlag,
 			utils.RollupMaxCalldataSizeFlag,
diff --git a/l2geth/cmd/utils/flags.go b/l2geth/cmd/utils/flags.go
index cc34a65e5..f1d5a0f4c 100644
--- a/l2geth/cmd/utils/flags.go
+++ b/l2geth/cmd/utils/flags.go
@@ -867,11 +867,6 @@ var (
 		Usage:  "Enable the verifier for mpc node",
 		EnvVar: "ROLLUP_VERIFIER_MPC_ENABLE",
 	}
-	RollupEigenDaBlockFlag = cli.Int64Flag{
-		Name:   "rollup.eigendablock",
-		Usage:  "Eigen DA Fee Block number",
-		EnvVar: "ROLLUP_EIGEN_DA_BLOCK",
-	}
 	RollupMaxCalldataSizeFlag = cli.IntFlag{
 		Name:   "rollup.maxcalldatasize",
 		Usage:  "Maximum allowed calldata size for Queue Origin Sequencer Txs",
@@ -1245,9 +1240,6 @@ func setRollup(ctx *cli.Context, cfg *rollup.Config) {
 	if ctx.GlobalIsSet(RollupMpcVerifierFlag.Name) {
 		cfg.MpcVerifier = true
 	}
-	if ctx.GlobalIsSet(RollupEigenDaBlockFlag.Name) {
-		cfg.EigenDaBlock = ctx.GlobalInt64(RollupEigenDaBlockFlag.Name)
-	}
 	if ctx.GlobalIsSet(RollupFeeThresholdDownFlag.Name) {
 		val := ctx.GlobalFloat64(RollupFeeThresholdDownFlag.Name)
 		cfg.FeeThresholdDown = new(big.Float).SetFloat64(val)
diff --git a/l2geth/consensus/clique/clique.go b/l2geth/consensus/clique/clique.go
index 507ec94fb..dce87b7c0 100644
--- a/l2geth/consensus/clique/clique.go
+++ b/l2geth/consensus/clique/clique.go
@@ -34,6 +34,7 @@ import (
 	"github.com/mantlenetworkio/mantle/l2geth/consensus/misc"
 	"github.com/mantlenetworkio/mantle/l2geth/core/state"
 	"github.com/mantlenetworkio/mantle/l2geth/core/types"
+	"github.com/mantlenetworkio/mantle/l2geth/core/upgrade"
 	"github.com/mantlenetworkio/mantle/l2geth/crypto"
 	"github.com/mantlenetworkio/mantle/l2geth/ethdb"
 	"github.com/mantlenetworkio/mantle/l2geth/log"
@@ -50,9 +51,6 @@ const (
 	inmemorySignatures = 4096 // Number of recent block signatures to keep in memory
 
 	wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers
-
-	preUpgradedGaslimit = 15000000 //this params is only used for testnet
-	testnetChainID      = 5001
 )
 
 // Clique proof-of-authority protocol constants.
@@ -587,12 +585,11 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainReader, header *types.
 	//if UpdateGasLimitBlock not set , will not changed, for mainnet.
 	//if UpdateGasLimitBlock = 0, from the genesis block
 	//if UpdateGasLimitBlock = x, from the x
-	if chain.Config().UpdateGasLimitBlock != nil && chain.Config().ChainID.Int64() == testnetChainID {
+	mantleUpgradeConfig := upgrade.NewMantleUpgradeConfig(chain.Config().ChainID)
+	if !mantleUpgradeConfig.IsUpdateGasLimitBlock(header.Number) {
 		//for testnet, when the UpdateGasLimitBlock  is actived, we must update the gaslimit for all of block
 		//which is after the "updategaslimit" block
-		if !chain.Config().IsUpdateGasLimitBlock(header.Number) {
-			header.GasLimit = preUpgradedGaslimit
-		}
+		header.GasLimit = uint64(upgrade.PreUpgradedGaslimit)
 	}
 
 	// Assemble and return the final block for sealing
diff --git a/l2geth/core/blockchain.go b/l2geth/core/blockchain.go
index 37c95dd05..ad3c4fdf6 100644
--- a/l2geth/core/blockchain.go
+++ b/l2geth/core/blockchain.go
@@ -302,6 +302,10 @@ func (bc *BlockChain) getProcInterrupt() bool {
 	return atomic.LoadInt32(&bc.procInterrupt) == 1
 }
 
+func (bc *BlockChain) ChainDb() ethdb.Database {
+	return bc.db
+}
+
 // GetVMConfig returns the block chain VM config.
 func (bc *BlockChain) GetVMConfig() *vm.Config {
 	return &bc.vmConfig
diff --git a/l2geth/core/evm.go b/l2geth/core/evm.go
index f3e1aa2d8..5151c61f6 100644
--- a/l2geth/core/evm.go
+++ b/l2geth/core/evm.go
@@ -23,6 +23,7 @@ import (
 	"github.com/mantlenetworkio/mantle/l2geth/consensus"
 	"github.com/mantlenetworkio/mantle/l2geth/core/types"
 	"github.com/mantlenetworkio/mantle/l2geth/core/vm"
+	"github.com/mantlenetworkio/mantle/l2geth/ethdb"
 	"github.com/mantlenetworkio/mantle/l2geth/rollup/dump"
 	"github.com/mantlenetworkio/mantle/l2geth/rollup/rcfg"
 )
@@ -35,6 +36,9 @@ type ChainContext interface {
 
 	// GetHeader returns the hash corresponding to their hash.
 	GetHeader(common.Hash, uint64) *types.Header
+
+	// ChainDb returns eth database, interact with database directly
+	ChainDb() ethdb.Database
 }
 
 // NewEVMBlockContext creates a new context for use in the EVM.
diff --git a/l2geth/core/genesis.go b/l2geth/core/genesis.go
index 16d534d88..2fc79a155 100644
--- a/l2geth/core/genesis.go
+++ b/l2geth/core/genesis.go
@@ -31,6 +31,7 @@ import (
 	"github.com/mantlenetworkio/mantle/l2geth/core/rawdb"
 	"github.com/mantlenetworkio/mantle/l2geth/core/state"
 	"github.com/mantlenetworkio/mantle/l2geth/core/types"
+	"github.com/mantlenetworkio/mantle/l2geth/core/upgrade"
 	"github.com/mantlenetworkio/mantle/l2geth/crypto"
 	"github.com/mantlenetworkio/mantle/l2geth/ethdb"
 	"github.com/mantlenetworkio/mantle/l2geth/log"
@@ -42,8 +43,6 @@ import (
 //go:generate gencodec -type GenesisAccount -field-override genesisAccountMarshaling -out gen_genesis_account.go
 
 var errGenesisNoConfig = errors.New("genesis has no chain configuration")
-var testnetGenesisGaslimit = 15000000 //this params is only used for testnet
-var testnetChainID = 5001
 
 // Genesis specifies the header fields, state of a genesis block. It also defines hard
 // fork switch-over blocks through the chain configuration.
@@ -171,11 +170,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override
 			log.Info("Writing custom genesis block")
 		}
 		//for a new node from 0 to recent height, we must reset its genesis gaslimit to 150000000
-		if genesis.Config.ChainID.Int64() == int64(testnetChainID) {
+		if genesis.Config.ChainID.Int64() == params.MantleTestnetChainID.Int64() {
 			// updata gaslimt block is actived！we need to reset the gaslimit for genesis block
-			if genesis.Config.UpdateGasLimitBlock != nil {
-				genesis.GasLimit = uint64(testnetGenesisGaslimit)
-			}
+			genesis.GasLimit = uint64(upgrade.PreUpgradedGaslimit)
 		}
 		block, err := genesis.Commit(db)
 		if err != nil {
diff --git a/l2geth/core/state_processor.go b/l2geth/core/state_processor.go
index 28538c5b3..22cc6b3d1 100644
--- a/l2geth/core/state_processor.go
+++ b/l2geth/core/state_processor.go
@@ -98,11 +98,8 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
 	// Create a new environment which holds all relevant information
 	// about the transaction and calling mechanisms.
 	vmenv := vm.NewEVM(context, statedb, config, cfg)
-	if config.IsEigenDa(header.Number) {
-		vmenv.StateDB.SetCode(rcfg.L2GasPriceOracleAddress, rcfg.L2GasPriceOracleCode)
-	}
 
-	upgrade.CheckUpgrade(vmenv.StateDB, header.Number)
+	upgrade.CheckUpgrade(config.ChainID, vmenv.StateDB, bc.ChainDb(), header.Number, tx.L1BlockNumber())
 
 	// UsingBVM
 	// Compute the fee related information that is to be included
diff --git a/l2geth/core/types/gen_receipt_json.go b/l2geth/core/types/gen_receipt_json.go
index 5c7868562..870e945f5 100644
--- a/l2geth/core/types/gen_receipt_json.go
+++ b/l2geth/core/types/gen_receipt_json.go
@@ -31,10 +31,9 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
 		L1GasUsed         *hexutil.Big   `json:"l1GasUsed" gencodec:"required"`
 		L1Fee             *hexutil.Big   `json:"l1Fee" gencodec:"required"`
 		FeeScalar         *big.Float     `json:"l1FeeScalar" gencodec:"required"`
-        // use eigenDA
-		DAGasPrice        *hexutil.Big   `json:"daGasPrice" gencodec:"required"`
-		DAGasUsed         *hexutil.Big   `json:"daGasUsed" gencodec:"required"`
-		DAFee             *hexutil.Big   `json:"daFee" gencodec:"required"`
+		DAGasPrice        *big.Int       `json:"daGasPrice" gencodec:"required"`
+		DAGasUsed         *big.Int       `json:"daGasUsed" gencodec:"required"`
+		DAFee             *big.Int       `json:"daFee" gencodec:"required"`
 	}
 	var enc Receipt
 	enc.PostState = r.PostState
@@ -52,9 +51,9 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
 	enc.L1GasUsed = (*hexutil.Big)(r.L1GasUsed)
 	enc.L1Fee = (*hexutil.Big)(r.L1Fee)
 	enc.FeeScalar = r.FeeScalar
-	enc.DAGasPrice = (*hexutil.Big)(r.DAGasPrice)
-	enc.DAGasUsed = (*hexutil.Big)(r.DAGasUsed)
-	enc.DAFee = (*hexutil.Big)(r.DAFee)
+	enc.DAGasPrice = r.DAGasPrice
+	enc.DAGasUsed = r.DAGasUsed
+	enc.DAFee = r.DAFee
 	return json.Marshal(&enc)
 }
 
@@ -76,9 +75,9 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
 		L1GasUsed         *hexutil.Big    `json:"l1GasUsed" gencodec:"required"`
 		L1Fee             *hexutil.Big    `json:"l1Fee" gencodec:"required"`
 		FeeScalar         *big.Float      `json:"l1FeeScalar" gencodec:"required"`
-		DAGasPrice        *hexutil.Big    `json:"daGasPrice" gencodec:"required"`
-		DAGasUsed         *hexutil.Big    `json:"daGasUsed" gencodec:"required"`
-		DAFee             *hexutil.Big    `json:"daFee" gencodec:"required"`
+		DAGasPrice        *big.Int        `json:"daGasPrice" gencodec:"required"`
+		DAGasUsed         *big.Int        `json:"daGasUsed" gencodec:"required"`
+		DAFee             *big.Int        `json:"daFee" gencodec:"required"`
 	}
 	var dec Receipt
 	if err := json.Unmarshal(input, &dec); err != nil {
@@ -138,14 +137,17 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
 		return errors.New("missing required field 'l1FeeScalar' for Receipt")
 	}
 	r.FeeScalar = dec.FeeScalar
-	r.DAGasPrice = (*big.Int)(dec.DAGasPrice)
+	if dec.DAGasPrice == nil {
+		return errors.New("missing required field 'daGasPrice' for Receipt")
+	}
+	r.DAGasPrice = dec.DAGasPrice
 	if dec.DAGasUsed == nil {
-		return errors.New("missing required field 'l1GasUsed' for Receipt")
+		return errors.New("missing required field 'daGasUsed' for Receipt")
 	}
-	r.DAGasUsed = (*big.Int)(dec.DAGasUsed)
+	r.DAGasUsed = dec.DAGasUsed
 	if dec.DAFee == nil {
-		return errors.New("missing required field 'l1Fee' for Receipt")
+		return errors.New("missing required field 'daFee' for Receipt")
 	}
-	r.DAFee = (*big.Int)(dec.DAFee)
+	r.DAFee = dec.DAFee
 	return nil
 }
diff --git a/l2geth/core/types/receipt.go b/l2geth/core/types/receipt.go
index 135ba356b..4015b291c 100644
--- a/l2geth/core/types/receipt.go
+++ b/l2geth/core/types/receipt.go
@@ -72,9 +72,9 @@ type Receipt struct {
 	L1GasUsed  *big.Int   `json:"l1GasUsed" gencodec:"required"`
 	L1Fee      *big.Int   `json:"l1Fee" gencodec:"required"`
 	FeeScalar  *big.Float `json:"l1FeeScalar" gencodec:"required"`
-	DAGasPrice *big.Int   `json:"daGasPrice" `
-	DAGasUsed  *big.Int   `json:"daGasUsed" `
-	DAFee      *big.Int   `json:"daFee"`
+	DAGasPrice *big.Int   `json:"daGasPrice" gencodec:"required"`
+	DAGasUsed  *big.Int   `json:"daGasUsed" gencodec:"required"`
+	DAFee      *big.Int   `json:"daFee" gencodec:"required"`
 }
 
 type receiptMarshaling struct {
diff --git a/l2geth/core/upgrade/config.go b/l2geth/core/upgrade/config.go
new file mode 100644
index 000000000..0d4e7883c
--- /dev/null
+++ b/l2geth/core/upgrade/config.go
@@ -0,0 +1,151 @@
+package upgrade
+
+import (
+	"math/big"
+
+	"github.com/mantlenetworkio/mantle/l2geth/params"
+)
+
+type Config struct {
+	chainID *big.Int
+
+	// tssRewardL2Block
+	// Once the Layer 2 block height reaches this threshold, the upgrade operation will be executed
+	tssRewardL2Block *big.Int
+
+	// mantleTokenL2Block
+	// Once the Layer 2 block height reaches this threshold, the upgrade operation will be executed
+	mantleTokenL2Block *big.Int
+
+	// updateGasLimitL2Block
+	// Once the Layer 2 block height reaches this threshold, the upgrade operation will be executed
+	updateGasLimitL2Block *big.Int
+
+	// eigenDaL2Block
+	// Once the Layer 2 block height reaches this threshold, the upgrade operation will be executed
+	eigenDaL2Block *big.Int
+
+	// mockUpgradeL1Block
+	// Once the Layer 1 block height reaches this threshold, the upgrade operation will be executed
+	mockUpgradeL1Block *big.Int
+	// mockUpgradeL1BlockUpgradeStatus record upgrade status for mockUpgradeL1Block
+	// Record the upgrade status only for upgrades based on L1 block number, as L2 blocks corresponding
+	// to L1 blocks may not have transactions.
+	// By checking if the L1 block number is greater than or equal to a certain value, we can ensure
+	// that the upgrade operation will be triggered.
+	// Also, keep a record of the upgrade to prevent it from being executed repeatedly for subsequent L2 heights.
+	mockUpgradeL1BlockUpgradeStatus bool
+}
+
+var (
+	MainnetConfig = &Config{
+		chainID:               params.MantleMainnetChainID,
+		tssRewardL2Block:      big.NewInt(-1),
+		mantleTokenL2Block:    big.NewInt(-1),
+		eigenDaL2Block:        big.NewInt(-1),
+		updateGasLimitL2Block: big.NewInt(-1),
+		mockUpgradeL1Block:    big.NewInt(-1),
+	}
+
+	TestnetConfig = &Config{
+		chainID:               params.MantleTestnetChainID,
+		tssRewardL2Block:      big.NewInt(11_000_000),
+		mantleTokenL2Block:    big.NewInt(11_000_000),
+		eigenDaL2Block:        big.NewInt(8_280_000),
+		updateGasLimitL2Block: big.NewInt(222_073),
+		mockUpgradeL1Block:    big.NewInt(-1),
+	}
+
+	QAConfig = &Config{
+		chainID:               params.MantleQAChainID,
+		tssRewardL2Block:      big.NewInt(-1),
+		mantleTokenL2Block:    big.NewInt(-1),
+		eigenDaL2Block:        big.NewInt(-1),
+		updateGasLimitL2Block: big.NewInt(-1),
+		mockUpgradeL1Block:    big.NewInt(-1),
+	}
+
+	LocalConfig = &Config{
+		chainID:               params.MantleLocalChainID,
+		tssRewardL2Block:      big.NewInt(-1),
+		mantleTokenL2Block:    big.NewInt(-1),
+		eigenDaL2Block:        big.NewInt(-1),
+		updateGasLimitL2Block: big.NewInt(-1),
+		mockUpgradeL1Block:    big.NewInt(-1),
+	}
+)
+
+func NewMantleUpgradeConfig(chainID *big.Int) *Config {
+	switch chainID.Int64() {
+	case params.MantleMainnetChainID.Int64():
+		return MainnetConfig
+	case params.MantleTestnetChainID.Int64():
+		return TestnetConfig
+	case params.MantleQAChainID.Int64():
+		return QAConfig
+	case params.MantleLocalChainID.Int64():
+		return LocalConfig
+	default:
+		return LocalConfig
+	}
+}
+
+// IsTssReward returns whether num is either equal to the TssReward fork block or greater.
+// Compare with L2 BlockNumber
+func (c *Config) IsTssReward(num *big.Int) bool {
+	return isExactBlockForked(c.tssRewardL2Block, num)
+}
+
+// IsMantleToken returns whether num is either equal to the IsMantleToken fork block or greater.
+// Compare with L2 BlockNumber
+func (c *Config) IsMantleToken(num *big.Int) bool {
+	return isExactBlockForked(c.mantleTokenL2Block, num)
+}
+
+// IsEigenDa returns whether num is either equal to the IsEigenDa fork block or greater.
+// Compare with L2 BlockNumber
+func (c *Config) IsEigenDa(num *big.Int) bool {
+	return isExactBlockForked(c.eigenDaL2Block, num)
+}
+
+// IsUpdateGasLimitBlock returns whether num is either equal to the IsUpdateGasLimitBlock fork block or greater.
+// Compare with L2 BlockNumber
+func (c *Config) IsUpdateGasLimitBlock(num *big.Int) bool {
+	return isBlockForked(c.updateGasLimitL2Block, num)
+}
+
+// IsMockUpgradeBasedOnL1BlockNumber returns whether num is either equal to the IsMantleToken fork block or greater.
+// Compare with L1 BlockNumber
+func (c *Config) IsMockUpgradeBasedOnL1BlockNumber(num *big.Int) bool {
+	return isBlockForked(c.mockUpgradeL1Block, num)
+}
+
+// isBlockForked returns whether a fork scheduled at block s is active at the
+// given head block.
+// isBlockForked is used to compare with Layer1 block height
+func isBlockForked(s, head *big.Int) bool {
+	if s == nil || head == nil {
+		return false
+	}
+
+	if s.Cmp(big.NewInt(0)) <= 0 {
+		return false
+	}
+
+	return s.Cmp(head) <= 0
+}
+
+// isExactBlockForked returns whether a fork scheduled at block s is active at the
+// given head block.
+// isExactBlockForked is used to compare with Layer2 block height
+func isExactBlockForked(s, head *big.Int) bool {
+	if s == nil || head == nil {
+		return false
+	}
+
+	if s.Cmp(big.NewInt(0)) <= 0 {
+		return false
+	}
+
+	return s.Cmp(head) == 0
+}
diff --git a/l2geth/core/upgrade/module.go b/l2geth/core/upgrade/module.go
index 1c1ea616d..3c085e36d 100644
--- a/l2geth/core/upgrade/module.go
+++ b/l2geth/core/upgrade/module.go
@@ -4,67 +4,96 @@ import (
 	"math/big"
 
 	"github.com/ethereum/go-ethereum/common/hexutil"
+
 	"github.com/mantlenetworkio/mantle/l2geth/common"
 	"github.com/mantlenetworkio/mantle/l2geth/core/vm"
+	"github.com/mantlenetworkio/mantle/l2geth/ethdb"
 	"github.com/mantlenetworkio/mantle/l2geth/log"
 	"github.com/mantlenetworkio/mantle/l2geth/rollup/rcfg"
 )
 
 /*
- *    this module is used to design simple upgrade for l2geth setcode logic.
- *    for future upgrade, we don't need to change the genesis.json and add the new height into it,
- *    but simply add the height, address, code into the var, and add a new function such as l2GasOracleMockUpgrade
- *    at the same time, make sure this new function is involved into the CheckUpgrade function.
-
- *    to be clearifed, if we have the completely governece mechanism, we could use a better way to do it.
- *    we could wrap the setcode' code and address into a special-transaction,
- *    for example, which its address is 0x420000000000000000000000000000000000001F, and finally executed in the evm.
- *    by this way, we don't need to stop the l2geth and verifier node, a way of on-chain upgrade.
+ * There are two scenarios for the upgrade operation.
+ * 1. The first scenario is to execute an upgrade operation at a specific height, such as 'setCode'.
+ * 2. The second scenario is to follow the previous logic before a certain height,
+ * and switch to new processing logic after that height.
+
+ * For the first scenario, we use 'isExactBlockForked' to determine the upgrade height and ensure
+ * that the operation is triggered only once at a specific height.
+ * For the second scenario, we use 'isBlockForked' to determine the upgrade height and ensure
+ * that different logic is executed before and after the upgrade.
+
+ * In addition, we have two options for selecting the upgrade height: L1 block and L2 block.
+ * For L2 blocks, they are strictly increasing and consecutive. We need to choose between 'isBlockForked'
+ * and 'isExactBlockForked' based on the specific situation.
+ * For L1 blocks, they are synchronized from the sync service, and there are two possible scenarios.
+ * 1. In the first scenario, the synchronized blocks may not be consecutive, resulting in block gaps.
+ * 2. In the second scenario, there may be no corresponding L2 block generated at the same time as the L1 block.
+ * So we need to use 'isBlockForked' to ensure that the upgrade operation is always executed.
+ * We may also need to keep a record of the upgrade operation to prevent it from being executed repeatedly.
  */
 
 var (
-	// mantle token upgrade height for testnet
-	MantleTokenUpgradeHeight = -1
-
-	L2GasPriceOracleHeight = -1
-	//qa height
-	L2TssRewardHeight = -1
-	// L2GasPriceOracleAddress is the address of the BVM_GasPriceOracle
-	// predeploy
-	L2GasPriceOracleAddress = common.HexToAddress("0x420000000000000000000000000000000000000F")
 	// L2TssRewardAddress is the address of the TssRewardContract
 	// predeploy
 	L2TssRewardAddress = common.HexToAddress("0x4200000000000000000000000000000000000020")
-	// code Compile from commit 5721560308276eafef92e688cc03207ed2c00f53
-	L2GasPriceOracleCode, _ = hexutil.Decode("0x608060405234801561001057600080fd5b50600436106101585760003560e01c8063715018a6116100c3578063de26c4a11161007c578063de26c4a114610367578063ea01cd3614610397578063f2fde38b146103b5578063f45e65d8146103d1578063fc55b138146103ef578063fe173b971461040b57610158565b8063715018a6146102cf5780638c8885c8146102d95780638da5cb5b146102f5578063bede39b514610313578063bf1fe4201461032f578063c76478321461034b57610158565b806345c51a381161011557806345c51a381461020d57806349948e0e14610229578063519b4bd31461025957806355161913146102775780635cbe497a1461029557806370465597146102b357610158565b80630c18c1621461015d5780630d1e43a01461017b5780630e6faf1e1461019957806328800578146101b7578063313ce567146101d35780633577afc5146101f1575b600080fd5b610165610429565b6040516101729190610b4f565b60405180910390f35b61018361042f565b6040516101909190610b4f565b60405180910390f35b6101a1610439565b6040516101ae9190610b4f565b60405180910390f35b6101d160048036038101906101cc9190610baa565b61043f565b005b6101db6104d8565b6040516101e89190610b4f565b60405180910390f35b61020b60048036038101906102069190610baa565b6104de565b005b61022760048036038101906102229190610baa565b610527565b005b610243600480360381019061023e9190610d1d565b610570565b6040516102509190610b4f565b60405180910390f35b6102616105d2565b60405161026e9190610b4f565b60405180910390f35b61027f6105d8565b60405161028c9190610b4f565b60405180910390f35b61029d6105de565b6040516102aa9190610b4f565b60405180910390f35b6102cd60048036038101906102c89190610baa565b6105e4565b005b6102d761062d565b005b6102f360048036038101906102ee9190610baa565b610641565b005b6102fd61068a565b60405161030a9190610da7565b60405180910390f35b61032d60048036038101906103289190610baa565b6106b3565b005b61034960048036038101906103449190610baa565b6106fc565b005b61036560048036038101906103609190610baa565b610745565b005b610381600480360381019061037c9190610d1d565b6107de565b60405161038e9190610b4f565b60405180910390f35b61039f61089d565b6040516103ac9190610da7565b60405180910390f35b6103cf60048036038101906103ca9190610dee565b6108c3565b005b6103d9610947565b6040516103e69190610b4f565b60405180910390f35b61040960048036038101906104049190610baa565b61094d565b005b6104136109e6565b6040516104209190610b4f565b60405180910390f35b60035481565b6000600654905090565b600a5481565b6104476109ec565b8060008114806104575750600181145b610496576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161048d90610e78565b60405180910390fd5b81600a819055507f65cacb453bbeab72658947058c43b2a6c7dfcca1c9d96ba1bc470d346929b288826040516104cc9190610b4f565b60405180910390a15050565b60055481565b6104e66109ec565b806003819055507f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb48160405161051c9190610b4f565b60405180910390a150565b61052f6109ec565b806009819055507f5af81f5214eaf8c64101a8fde536abc770ef62af9e14d15e2b0b68760b2028f5816040516105659190610b4f565b60405180910390a150565b60008061057c836107de565b905060006002548261058e9190610ec7565b90506000600554600a6105a19190611054565b90506000600454836105b39190610ec7565b9050600082826105c391906110ce565b90508095505050505050919050565b60025481565b60075481565b60095481565b6105ec6109ec565b806004819055507f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a816040516106229190610b4f565b60405180910390a150565b6106356109ec565b61063f6000610a6a565b565b6106496109ec565b806005819055507fd68112a8707e326d08be3656b528c1bcc5bbbfc47f4177e2179b14d8640838c18160405161067f9190610b4f565b60405180910390a150565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6106bb6109ec565b806002819055507f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c44816040516106f19190610b4f565b60405180910390a150565b6107046109ec565b806001819055507ffcdccc6074c6c42e4bd578aa9870c697dc976a270968452d2b8c8dc369fae3968160405161073a9190610b4f565b60405180910390a150565b61074d6109ec565b80600081148061075d5750600181145b61079c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079390610e78565b60405180910390fd5b816006819055507fd1eaae13a99b475ddca546a1b4a45052c66c14049997f44a1731a8e7167981a7826040516107d29190610b4f565b60405180910390a15050565b6000806000905060005b835181101561087357600060f81b848281518110610809576108086110ff565b5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141561085057600482610849919061112e565b9150610860565b60108261085d919061112e565b91505b808061086b90611184565b9150506107e8565b50600060035482610884919061112e565b905061044081610894919061112e565b92505050919050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6108cb6109ec565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561093b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109329061123f565b60405180910390fd5b61094481610a6a565b50565b60045481565b6109556109ec565b8060008114806109655750600181145b6109a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099b90610e78565b60405180910390fd5b816007819055507f49244d4195584d0644398167ca8caa7b98ee36b674e4b4d2a2640749b27eafb7826040516109da9190610b4f565b60405180910390a15050565b60015481565b6109f4610b2e565b73ffffffffffffffffffffffffffffffffffffffff16610a1261068a565b73ffffffffffffffffffffffffffffffffffffffff1614610a68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5f906112ab565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600033905090565b6000819050919050565b610b4981610b36565b82525050565b6000602082019050610b646000830184610b40565b92915050565b6000604051905090565b600080fd5b600080fd5b610b8781610b36565b8114610b9257600080fd5b50565b600081359050610ba481610b7e565b92915050565b600060208284031215610bc057610bbf610b74565b5b6000610bce84828501610b95565b91505092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610c2a82610be1565b810181811067ffffffffffffffff82111715610c4957610c48610bf2565b5b80604052505050565b6000610c5c610b6a565b9050610c688282610c21565b919050565b600067ffffffffffffffff821115610c8857610c87610bf2565b5b610c9182610be1565b9050602081019050919050565b82818337600083830152505050565b6000610cc0610cbb84610c6d565b610c52565b905082815260208101848484011115610cdc57610cdb610bdc565b5b610ce7848285610c9e565b509392505050565b600082601f830112610d0457610d03610bd7565b5b8135610d14848260208601610cad565b91505092915050565b600060208284031215610d3357610d32610b74565b5b600082013567ffffffffffffffff811115610d5157610d50610b79565b5b610d5d84828501610cef565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610d9182610d66565b9050919050565b610da181610d86565b82525050565b6000602082019050610dbc6000830184610d98565b92915050565b610dcb81610d86565b8114610dd657600080fd5b50565b600081359050610de881610dc2565b92915050565b600060208284031215610e0457610e03610b74565b5b6000610e1284828501610dd9565b91505092915050565b600082825260208201905092915050565b7f696e76616c69642076616c75652c6d7573742062652030206f72203100000000600082015250565b6000610e62601c83610e1b565b9150610e6d82610e2c565b602082019050919050565b60006020820190508181036000830152610e9181610e55565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610ed282610b36565b9150610edd83610b36565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610f1657610f15610e98565b5b828202905092915050565b60008160011c9050919050565b6000808291508390505b6001851115610f7857808604811115610f5457610f53610e98565b5b6001851615610f635780820291505b8081029050610f7185610f21565b9450610f38565b94509492505050565b600082610f91576001905061104d565b81610f9f576000905061104d565b8160018114610fb55760028114610fbf57610fee565b600191505061104d565b60ff841115610fd157610fd0610e98565b5b8360020a915084821115610fe857610fe7610e98565b5b5061104d565b5060208310610133831016604e8410600b84101617156110235782820a90508381111561101e5761101d610e98565b5b61104d565b6110308484846001610f2e565b9250905081840481111561104757611046610e98565b5b81810290505b9392505050565b600061105f82610b36565b915061106a83610b36565b92506110977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484610f81565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006110d982610b36565b91506110e483610b36565b9250826110f4576110f361109f565b5b828204905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600061113982610b36565b915061114483610b36565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561117957611178610e98565b5b828201905092915050565b600061118f82610b36565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156111c2576111c1610e98565b5b600182019050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000611229602683610e1b565b9150611234826111cd565b604082019050919050565b600060208201905081810360008301526112588161121c565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000611295602083610e1b565b91506112a08261125f565b602082019050919050565b600060208201905081810360008301526112c481611288565b905091905056fea2646970667358221220a27df6f5432a84da559421985a625e69e24b1f6cad2c3be323fb45294f6add1864736f6c634300080b0033")
 	// code Compile from commit 52b6bbc52bbad5b971fd51a76d1b9b87d342e9f3
 	L2GasRewardCode, _ = hexutil.Decode("0x6080604052600436106101f25760003560e01c8063715018a61161010d578063d8111a57116100a0578063ea01cd361161006f578063ea01cd361461058e578063ebc73e65146105ae578063f2fde38b146105ce578063f5cf673b146105ee578063fad9aba31461060e57600080fd5b8063d8111a571461050c578063da62fba914610522578063e5efd58514610558578063e91a469e1461056e57600080fd5b8063b89ea402116100dc578063b89ea40214610478578063ceddc021146104a5578063cf172403146104ca578063d4440a36146104f757600080fd5b8063715018a6146104195780638da5cb5b1461042e578063904ad6be1461044c578063aa13e8c21461046257600080fd5b806327c8f835116101855780633cb747bf116101545780633cb747bf146103a25780633ccfd60b146103c25780634e71d92d146103d757806352674ea5146103ec57600080fd5b806327c8f8351461032f5780632c79db111461034f5780633310ceeb146103625780633b52c31e1461038257600080fd5b806315c6f166116101c157806315c6f166146102ce57806319d509a1146102e35780631a39d8ef146102f9578063208695eb1461030f57600080fd5b80630fae75d9146101fe57806310a7fd7b14610220578063110b7eb01461026057806313e7c9d81461029857600080fd5b366101f957005b600080fd5b34801561020a57600080fd5b5061021e61021936600461127f565b610624565b005b34801561022c57600080fd5b5061024d61023b366004611321565b60346020526000908152604090205481565b6040519081526020015b60405180910390f35b34801561026c57600080fd5b50603554610280906001600160a01b031681565b6040516001600160a01b039091168152602001610257565b3480156102a457600080fd5b506102806102b336600461134f565b6040602081905260009182529020546001600160a01b031681565b3480156102da57600080fd5b5061024d61083f565b3480156102ef57600080fd5b5061024d60385481565b34801561030557600080fd5b5061024d60395481565b34801561031b57600080fd5b50604454610280906001600160a01b031681565b34801561033b57600080fd5b50603654610280906001600160a01b031681565b34801561035b57600080fd5b504761024d565b34801561036e57600080fd5b5061021e61037d36600461134f565b61086a565b34801561038e57600080fd5b5061021e61039d366004611321565b6108b6565b3480156103ae57600080fd5b50600154610280906001600160a01b031681565b3480156103ce57600080fd5b5061021e6108e5565b3480156103e357600080fd5b5061021e610953565b3480156103f857600080fd5b5061024d61040736600461134f565b60436020526000908152604090205481565b34801561042557600080fd5b5061021e610a8f565b34801561043a57600080fd5b506000546001600160a01b0316610280565b34801561045857600080fd5b5061024d603d5481565b34801561046e57600080fd5b5061024d603e5481565b34801561048457600080fd5b5061024d61049336600461134f565b60426020526000908152604090205481565b3480156104b157600080fd5b506104ba610ac3565b6040519015158152602001610257565b3480156104d657600080fd5b5061024d6104e536600461134f565b603f6020526000908152604090205481565b34801561050357600080fd5b5061024d610bf2565b34801561051857600080fd5b5061024d603b5481565b34801561052e57600080fd5b5061028061053d36600461134f565b6041602052600090815260409020546001600160a01b031681565b34801561056457600080fd5b5061024d603a5481565b34801561057a57600080fd5b5061021e61058936600461134f565b610c1c565b34801561059a57600080fd5b50603c54610280906001600160a01b031681565b3480156105ba57600080fd5b5061021e6105c9366004611321565b610c68565b3480156105da57600080fd5b5061021e6105e936600461134f565b610c97565b3480156105fa57600080fd5b5061021e61060936600461136c565b610d2f565b34801561061a57600080fd5b5061024d60375481565b603c546001600160a01b03166106426001546001600160a01b031690565b6001600160a01b0316336001600160a01b03161461067b5760405162461bcd60e51b8152600401610672906113a5565b60405180910390fd5b806001600160a01b03166106976001546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b1580156106cf57600080fd5b505afa1580156106e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070791906113f3565b6001600160a01b03161461072d5760405162461bcd60e51b815260040161067290611410565b6000603a54600014156107455750603a849055610837565b603a5485116107b15760405162461bcd60e51b815260206004820152603260248201527f61726773205f626174636854696d65206d757374206774686572207468616e206044820152716c617374206c617374426174636854696d6560701b6064820152608401610672565b6037546107bc61083f565b603a546107c99088611476565b6107d3919061148d565b6107dd91906114ac565b600060375590506107ef818585610ece565b7ff533ef50019763ee9d95ad46e28350b533c11edd472ae7be93e8fae83c1b6d99603a54868387876040516108289594939291906114c4565b60405180910390a150603a8490555b505050505050565b60006108656301e13380603b54670de0b6b3a764000061085f919061148d565b90610f98565b905090565b6000546001600160a01b031633146108945760405162461bcd60e51b81526004016106729061152d565b604480546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146108e05760405162461bcd60e51b81526004016106729061152d565b603b55565b6000546001600160a01b0316331461090f5760405162461bcd60e51b81526004016106729061152d565b471561095157600080546040516001600160a01b03909116914780156108fc02929091818181858888f1935050505015801561094f573d6000803e3d6000fd5b505b565b336000908152604160205260409020546001600160a01b0316806109895760405162461bcd60e51b815260040161067290611562565b6002805414156109db5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610672565b60028055336000908152604160205260408120546001600160a01b031690610a0282610fa4565b90508015610a655760405162461bcd60e51b815260206004820152602a60248201527f706c65617365207761697420666f72207468652077616974696e6720706572696044820152696f6420746f207061737360b01b6064820152608401610672565b610a6e82611054565b506001600160a01b0316600090815260426020526040812055506001600255565b6000546001600160a01b03163314610ab95760405162461bcd60e51b81526004016106729061152d565b6109516000611217565b336000908152604160205260408120546001600160a01b031680610af95760405162461bcd60e51b815260040161067290611562565b336000908152604160209081526040808320546001600160a01b03168084526042909252909120548015610bbb5760405162461bcd60e51b815260206004820152605960248201527f596f75206861766520616c726561647920696e6974696174656420612072657160448201527f7565737420746f20636c61696d2c20706c65617365207761697420666f72207460648201527f68652077616974696e6720706572696f6420746f207061737300000000000000608482015260a401610672565b506001600160a01b03166000908152604260209081526040808320429055603f825280832054604390925290912055600191505090565b336000908152604160205260408120546001600160a01b031681610c1582610fa4565b9392505050565b6000546001600160a01b03163314610c465760405162461bcd60e51b81526004016106729061152d565b603c80546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610c925760405162461bcd60e51b81526004016106729061152d565b603e55565b6000546001600160a01b03163314610cc15760405162461bcd60e51b81526004016106729061152d565b6001600160a01b038116610d265760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610672565b61094f81611217565b6044546001600160a01b0316610d4d6001546001600160a01b031690565b6001600160a01b0316336001600160a01b031614610d7d5760405162461bcd60e51b8152600401610672906113a5565b806001600160a01b0316610d996001546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b158015610dd157600080fd5b505afa158015610de5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e0991906113f3565b6001600160a01b031614610e2f5760405162461bcd60e51b815260040161067290611410565b6001600160a01b038381166000908152604060208190529020541615610e84576001600160a01b0380841660009081526040602081815281832054909316825260419092522080546001600160a01b03191690555b506001600160a01b0390811660008181526041602090815260408083208054959096166001600160a01b031995861681179096559482528490529290922080549091169091179055565b8215610f9357600080610ee18584610f98565b915060005b83811015610f5e576000858583818110610f0257610f026115b3565b9050602002016020810190610f17919061134f565b6001600160a01b0381166000908152603f6020526040812080549293508692909190610f449084906114ac565b90915550829150610f569050816115c9565b915050610ee6565b50610f69838361148d565b90506000610f778683611267565b9050801561083757603754610f8c9082611273565b6037555050505b505050565b6000610c1582846115e4565b6001600160a01b0381166000908152604260205260408120548061101b5760405162461bcd60e51b815260206004820152602860248201527f706c6561736520696e6974696174652061207265717565737420746f20636c616044820152671a5b48199a5c9cdd60c21b6064820152608401610672565b6000603e548261102b91906114ac565b9050600042821115611048576110414283611476565b905061104c565b5060005b949350505050565b6001600160a01b038116600090815260436020908152604080832054603f90925290912054818110156110c95760405162461bcd60e51b815260206004820181905260248201527f546865206e756d65726963616c2076616c756520697320696e636f72726563746044820152606401610672565b8147101561113f5760405162461bcd60e51b815260206004820152603c60248201527f54686520636f6e74726163742062616c616e636520697320696e73756666696360448201527f69656e7420746f2070617920746865207265776172642076616c7565000000006064820152608401610672565b81156111d0576001600160a01b038084166000908152604060208181528183205460438252828420849055603f9091529120549116908190611182908590611476565b6001600160a01b038087166000908152603f60205260408082209390935591519083169186156108fc02918791818181858888f193505050501580156111cc573d6000803e3d6000fd5b5050505b604080516001600160a01b0385168152602081018490527f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4910160405180910390a1505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000610c158284611476565b6000610c1582846114ac565b60008060008060006080868803121561129757600080fd5b85359450602086013563ffffffff811681146112b257600080fd5b935060408601359250606086013567ffffffffffffffff808211156112d657600080fd5b818801915088601f8301126112ea57600080fd5b8135818111156112f957600080fd5b8960208260051b850101111561130e57600080fd5b9699959850939650602001949392505050565b60006020828403121561133357600080fd5b5035919050565b6001600160a01b038116811461094f57600080fd5b60006020828403121561136157600080fd5b8135610c158161133a565b6000806040838503121561137f57600080fd5b823561138a8161133a565b9150602083013561139a8161133a565b809150509250929050565b6020808252602e908201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560408201526d1b985d5d1a195b9d1a58d85d195960921b606082015260800190565b60006020828403121561140557600080fd5b8151610c158161133a565b60208082526030908201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360408201526f732d646f6d61696e206d65737361676560801b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60008282101561148857611488611460565b500390565b60008160001904831182151516156114a7576114a7611460565b500290565b600082198211156114bf576114bf611460565b500190565b60006080820187835260208781850152866040850152608060608501528185835260a08501905086925060005b8681101561151f5783356115048161133a565b6001600160a01b0316825292820192908201906001016114f1565b509998505050505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f546865206d73672073656e646572206973206e6f7420617574686f72697a656460408201527010313c903a3432903b30b634b230ba37b960791b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60006000198214156115dd576115dd611460565b5060010190565b60008261160157634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220c1c3d22331acc8f305fd9a0684ef99bc996384985748db9533152498b0af0e9f64736f6c63430008090033")
+
+	// PreUpgradedGaslimit before updateGasLimit upgrade, the default gas limit is PreUpgradedGaslimit
+	PreUpgradedGaslimit = 15000000
 )
 
-func CheckUpgrade(statedb vm.StateDB, blockNumber *big.Int) {
-	l2GasOracleMockUpgrade(statedb, blockNumber)
-	l2TssRewardUpgrade(statedb, blockNumber)
-	mantleTokenAndWMantleUpgrade(statedb, blockNumber)
+// CheckUpgrade used to execute upgrade logic
+func CheckUpgrade(chainID *big.Int, statedb vm.StateDB, ethdb ethdb.Database, l2BlockNumber *big.Int, l1BlockNumber *big.Int) {
+	log.Info("CheckUpgrade", "chain id", chainID)
+	upgradeConfig := NewMantleUpgradeConfig(chainID)
+
+	// upgrade based on layer2 block height
+	l2TssRewardUpgrade(statedb, upgradeConfig, l2BlockNumber)
+	mantleTokenUpgrade(statedb, upgradeConfig, l2BlockNumber)
+	eigenDaUpgrade(statedb, upgradeConfig, l2BlockNumber)
+
+	// mock an upgrade based on layer1 block height
+	mockUpgradeBasedOnL1Block(statedb, ethdb, upgradeConfig, l1BlockNumber)
 }
 
-func l2GasOracleMockUpgrade(statedb vm.StateDB, blockNumber *big.Int) {
-	//this will not be executed because L2GasPriceOracleHeight = -1
-	// we use the pre-genesis way to upgrade the L2GasPriceOracleCode
-	if blockNumber.Int64() == int64(L2GasPriceOracleHeight) {
-		statedb.SetCode(L2GasPriceOracleAddress, L2GasPriceOracleCode)
+func l2TssRewardUpgrade(statedb vm.StateDB, chainConfig *Config, blockNumber *big.Int) {
+	if !chainConfig.IsTssReward(blockNumber) {
+		return
 	}
+
+	statedb.SetCode(L2TssRewardAddress, L2GasRewardCode)
+	log.Info("update l2 tss reward success", "address", L2TssRewardAddress)
 }
 
-func l2TssRewardUpgrade(statedb vm.StateDB, blockNumber *big.Int) {
-	//this will not be executed because L2TssRewardHeight = -1
-	// we use the pre-genesis way to upgrade the L2GasRewardCode
-	if blockNumber.Int64() == int64(L2TssRewardHeight) {
-		statedb.SetCode(L2TssRewardAddress, L2GasRewardCode)
+func mantleTokenUpgrade(statedb vm.StateDB, chainConfig *Config, blockNumber *big.Int) {
+	if !chainConfig.IsMantleToken(blockNumber) {
+		return
 	}
+
+	statedb.SetState(rcfg.L2MantleTokenAddress, rcfg.MantleTokenNameSlot, rcfg.MantleTokenNameValue)
+	statedb.SetState(rcfg.L2MantleTokenAddress, rcfg.MantleTokenSymbolSlot, rcfg.MantleTokenSymbolValue)
+	log.Info("update mantle token name & symbol", "address", rcfg.L2MantleTokenAddress)
 }
 
-func mantleTokenAndWMantleUpgrade(statedb vm.StateDB, blockNumber *big.Int) {
-	if blockNumber.Int64() != int64(MantleTokenUpgradeHeight) {
+func eigenDaUpgrade(statedb vm.StateDB, chainConfig *Config, blockNumber *big.Int) {
+	if !chainConfig.IsEigenDa(blockNumber) {
+		return
+	}
+
+	statedb.SetCode(rcfg.L2GasPriceOracleAddress, rcfg.L2GasPriceOracleCode)
+	log.Info("update eigen data success", "address", rcfg.L2GasPriceOracleAddress)
+}
+
+func mockUpgradeBasedOnL1Block(statedb vm.StateDB, ethdb ethdb.Database, chainConfig *Config, blockNumber *big.Int) {
+	if !chainConfig.IsMockUpgradeBasedOnL1BlockNumber(blockNumber) {
+		return
+	}
+
+	// To prevent the upgrade operation from being executed repeatedly,
+	// we need to check whether the upgrade has already taken place.
+	if existUpgradeFlag(ethdb, mockUpgradeFlag) {
 		return
 	}
 
@@ -72,7 +101,5 @@ func mantleTokenAndWMantleUpgrade(statedb vm.StateDB, blockNumber *big.Int) {
 	statedb.SetState(rcfg.L2MantleTokenAddress, rcfg.MantleTokenNameSlot, rcfg.MantleTokenNameValue)
 	statedb.SetState(rcfg.L2MantleTokenAddress, rcfg.MantleTokenSymbolSlot, rcfg.MantleTokenSymbolValue)
 
-	log.Info("update wrapped mantle token name & symbol", "address", rcfg.L2WrappedMantleTokenAddress)
-	statedb.SetState(rcfg.L2WrappedMantleTokenAddress, rcfg.WrappedMantleTokenNameSlot, rcfg.WrappedMantleTokenNameValue)
-	statedb.SetState(rcfg.L2WrappedMantleTokenAddress, rcfg.WrappedMantleTokenSymbolSlot, rcfg.WrappedMantleTokenSymbolValue)
+	writeUpgradeFlag(ethdb, mockUpgradeFlag, blockNumber.Bytes())
 }
diff --git a/l2geth/core/upgrade/upgrade_status_basedon_l1.go b/l2geth/core/upgrade/upgrade_status_basedon_l1.go
new file mode 100644
index 000000000..b82f6a4aa
--- /dev/null
+++ b/l2geth/core/upgrade/upgrade_status_basedon_l1.go
@@ -0,0 +1,47 @@
+package upgrade
+
+import (
+	"github.com/mantlenetworkio/mantle/l2geth/ethdb"
+	"github.com/mantlenetworkio/mantle/l2geth/log"
+)
+
+/*
+	For upgrade based on L1 block number, record if the upgrade took place.
+*/
+
+var (
+	mockUpgradeFlag = []byte("mockUpgradeFlag")
+)
+
+func readUpgradeFlag(db ethdb.Reader, key []byte) []byte {
+	exist, err := db.Has(key)
+	if err != nil {
+		log.Error("Failed to get upgrade status", "err", err)
+	}
+	if !exist {
+		return nil
+	}
+	data, err := db.Get(key)
+	if err != nil {
+		log.Error("Failed to get upgrade status", "err", err)
+	}
+	return data
+}
+
+func existUpgradeFlag(db ethdb.Reader, key []byte) bool {
+	exist, err := db.Has(key)
+	if err != nil {
+		log.Error("Failed to check upgrade status", "err", err)
+		return false
+	}
+
+	return exist
+}
+
+func writeUpgradeFlag(db ethdb.Writer, key, data []byte) error {
+	if err := db.Put(key, data); err != nil {
+		log.Error("Failed to write upgrade status", "err", err)
+		return err
+	}
+	return nil
+}
diff --git a/l2geth/eth/backend.go b/l2geth/eth/backend.go
index 413f59671..fb93740d6 100644
--- a/l2geth/eth/backend.go
+++ b/l2geth/eth/backend.go
@@ -144,9 +144,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
 	if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
 		return nil, genesisErr
 	}
-	if chainConfig.EigenDaBlock == nil {
-		chainConfig.EigenDaBlock = big.NewInt(config.Rollup.EigenDaBlock)
-	}
 	log.Info("Initialised chain configuration", "config", chainConfig)
 
 	eth := &Ethereum{
diff --git a/l2geth/light/lightchain.go b/l2geth/light/lightchain.go
index 5f4b30ecb..80e4411b0 100644
--- a/l2geth/light/lightchain.go
+++ b/l2geth/light/lightchain.go
@@ -211,6 +211,10 @@ func (lc *LightChain) ResetWithGenesisBlock(genesis *types.Block) {
 
 // Accessors
 
+func (lc *LightChain) ChainDb() ethdb.Database {
+	panic("not implemented")
+}
+
 // Engine retrieves the light chain's consensus engine.
 func (lc *LightChain) Engine() consensus.Engine { return lc.engine }
 
diff --git a/l2geth/params/config.go b/l2geth/params/config.go
index 9be8ed84e..76f04a632 100644
--- a/l2geth/params/config.go
+++ b/l2geth/params/config.go
@@ -31,7 +31,14 @@ var (
 	TestnetGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d")
 	RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")
 	GoerliGenesisHash  = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a")
-	MainnetChainID     = int64(5000)
+)
+
+// ChainID for Mantle network.
+var (
+	MantleMainnetChainID = big.NewInt(5000)
+	MantleTestnetChainID = big.NewInt(5001)
+	MantleQAChainID      = big.NewInt(1705003)
+	MantleLocalChainID   = big.NewInt(17)
 )
 
 // TrustedCheckpoints associates each known checkpoint with the genesis hash of
@@ -216,14 +223,14 @@ var (
 	//
 	// This configuration is intentionally not using keyed fields to force anyone
 	// adding flags to the config to also have to set these fields.
-	AllEthashProtocolChanges = &ChainConfig{big.NewInt(108), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), new(EthashConfig), nil}
+	AllEthashProtocolChanges = &ChainConfig{big.NewInt(108), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil}
 	// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
 	// and accepted by the Ethereum core developers into the Clique consensus.
 	//
 	// This configuration is intentionally not using keyed fields to force anyone
 	// adding flags to the config to also have to set these fields.
-	AllCliqueProtocolChanges = &ChainConfig{big.NewInt(420), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), nil, &CliqueConfig{Period: 0, Epoch: 30000}}
-	TestChainConfig          = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), new(EthashConfig), nil}
+	AllCliqueProtocolChanges = &ChainConfig{big.NewInt(420), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}}
+	TestChainConfig          = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil}
 	TestRules                = TestChainConfig.Rules(new(big.Int))
 
 	// OpMainnetChainID is the ID of Mantle's mainnet chain.
@@ -310,9 +317,6 @@ type ChainConfig struct {
 
 	EWASMBlock *big.Int `json:"ewasmBlock,omitempty"` // EWASM switch block (nil = no fork, 0 = already activated)
 
-	UpdateGasLimitBlock *big.Int `json:"updateGaslimitBlock,omitempty"` //  UpdateGasLimitBlock witch block (nil = no fork, 0 = already activated)
-	EigenDaBlock        *big.Int `json:"eigenDaBlock,omitempty"`        //  EigenDaBlock witch block (nil = no fork, 0 = already activated)
-
 	// Various consensus engines
 	Ethash *EthashConfig `json:"ethash,omitempty"`
 	Clique *CliqueConfig `json:"clique,omitempty"`
@@ -362,8 +366,6 @@ func (c *ChainConfig) String() string {
 		c.IstanbulBlock,
 		c.MuirGlacierBlock,
 		c.BerlinBlock,
-		c.UpdateGasLimitBlock,
-		c.EigenDaBlock,
 		engine,
 	)
 }
@@ -430,21 +432,6 @@ func (c *ChainConfig) IsEWASM(num *big.Int) bool {
 	return isForked(c.EWASMBlock, num)
 }
 
-// IsUpdateGasLimitBlock returns whether num represents a block number after the UpdateGasLimitBlock fork
-func (c *ChainConfig) IsUpdateGasLimitBlock(num *big.Int) bool {
-	return isForked(c.UpdateGasLimitBlock, num)
-}
-
-// IsEigenDa returns whether num represents a block number after the IsEigenDa fork
-func (c *ChainConfig) IsEigenDa(num *big.Int) bool {
-	// c.eigenda block maybe nil for mainnet
-	// in this case, we have write the code into genesis.json
-	if c.EigenDaBlock == nil && c.ChainID.Int64() == MainnetChainID {
-		return false
-	}
-	return c.EigenDaBlock.Cmp(num) == 0
-}
-
 // IsSDUpdate returns whether num represents a block number after the SD update fork
 func (c *ChainConfig) IsSDUpdate(num *big.Int) bool {
 	if c.ChainID.Cmp(OpMainnetChainID) == 0 {
@@ -557,12 +544,6 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi
 	if isForkIncompatible(c.EWASMBlock, newcfg.EWASMBlock, head) {
 		return newCompatError("ewasm fork block", c.EWASMBlock, newcfg.EWASMBlock)
 	}
-	if isForkIncompatible(c.UpdateGasLimitBlock, newcfg.UpdateGasLimitBlock, head) {
-		return newCompatError("UpdateGasLimitBlock fork block", c.UpdateGasLimitBlock, newcfg.UpdateGasLimitBlock)
-	}
-	if isForkIncompatible(c.EigenDaBlock, newcfg.EigenDaBlock, head) {
-		return newCompatError("EigenDa fork block", c.EigenDaBlock, newcfg.EigenDaBlock)
-	}
 	return nil
 }
 
@@ -631,8 +612,6 @@ type Rules struct {
 	IsHomestead, IsEIP150, IsEIP155, IsEIP158               bool
 	IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
 	IsBerlin, IsLondon                                      bool
-	IsUpdateGasLimitBlock                                   bool
-	IsEigenDa                                               bool
 }
 
 // Rules ensures c's ChainID is not nil.
@@ -642,17 +621,15 @@ func (c *ChainConfig) Rules(num *big.Int) Rules {
 		chainID = new(big.Int)
 	}
 	return Rules{
-		ChainID:               new(big.Int).Set(chainID),
-		IsHomestead:           c.IsHomestead(num),
-		IsEIP150:              c.IsEIP150(num),
-		IsEIP155:              c.IsEIP155(num),
-		IsEIP158:              c.IsEIP158(num),
-		IsByzantium:           c.IsByzantium(num),
-		IsConstantinople:      c.IsConstantinople(num),
-		IsPetersburg:          c.IsPetersburg(num),
-		IsIstanbul:            c.IsIstanbul(num),
-		IsBerlin:              c.IsBerlin(num),
-		IsUpdateGasLimitBlock: c.IsUpdateGasLimitBlock(num),
-		IsEigenDa:             c.IsEigenDa(num),
+		ChainID:          new(big.Int).Set(chainID),
+		IsHomestead:      c.IsHomestead(num),
+		IsEIP150:         c.IsEIP150(num),
+		IsEIP155:         c.IsEIP155(num),
+		IsEIP158:         c.IsEIP158(num),
+		IsByzantium:      c.IsByzantium(num),
+		IsConstantinople: c.IsConstantinople(num),
+		IsPetersburg:     c.IsPetersburg(num),
+		IsIstanbul:       c.IsIstanbul(num),
+		IsBerlin:         c.IsBerlin(num),
 	}
 }
diff --git a/l2geth/rollup/config.go b/l2geth/rollup/config.go
index ca9fae6a9..1b647bfc5 100644
--- a/l2geth/rollup/config.go
+++ b/l2geth/rollup/config.go
@@ -53,7 +53,4 @@ type Config struct {
 	RollupRole Role
 
 	MpcVerifier bool
-
-	// EigenDaFee blockNumber Config
-	EigenDaBlock int64
 }
diff --git a/packages/contracts/genesis/local.json b/packages/contracts/genesis/local.json
index a63ed7325..819c0ad05 100644
--- a/packages/contracts/genesis/local.json
+++ b/packages/contracts/genesis/local.json
@@ -1,5 +1,5 @@
 {
-    "commit": "d627d242fe19f50f344f1ff4b27532d1757303a6",
+    "commit": "42caabb8f723304f038f9027178b3810672fc60c",
     "config": {
         "chainId": 17,
         "homesteadBlock": 0,


Test patch:
diff --git a/l2geth/core/upgrade/config_test.go b/l2geth/core/upgrade/config_test.go
new file mode 100644
index 000000000..4cbe62891
--- /dev/null
+++ b/l2geth/core/upgrade/config_test.go
@@ -0,0 +1,112 @@
+package upgrade
+
+import (
+	"math/big"
+	"testing"
+
+	"github.com/mantlenetworkio/mantle/l2geth/params"
+)
+
+func TestConfig_IsTssReward(t *testing.T) {
+	upgradeConfig := NewMantleUpgradeConfig(params.MantleMainnetChainID)
+	result := upgradeConfig.IsTssReward(big.NewInt(11_000_000))
+	if result {
+		t.Error("tss reward could not used for mainnet")
+	}
+
+	upgradeConfig = NewMantleUpgradeConfig(params.MantleTestnetChainID)
+	result = upgradeConfig.IsTssReward(big.NewInt(11_000_000))
+	if !result {
+		t.Error("tss reward should used for testnet")
+	}
+
+	upgradeConfig = NewMantleUpgradeConfig(params.MantleTestnetChainID)
+	result = upgradeConfig.IsTssReward(big.NewInt(11_000_001))
+	if result {
+		t.Error("tss reward upgrade height has passed")
+	}
+
+	upgradeConfig = NewMantleUpgradeConfig(params.MantleTestnetChainID)
+	result = upgradeConfig.IsTssReward(big.NewInt(10_999_999))
+	if result {
+		t.Error("tss reward upgrade height does not reach to")
+	}
+}
+
+func TestConfig_IsMantleToken(t *testing.T) {
+	upgradeConfig := NewMantleUpgradeConfig(params.MantleMainnetChainID)
+	result := upgradeConfig.IsMantleToken(big.NewInt(11_000_000))
+	if result {
+		t.Error("mantle token upgrade could not used for mainnet")
+	}
+
+	upgradeConfig = NewMantleUpgradeConfig(params.MantleTestnetChainID)
+	result = upgradeConfig.IsMantleToken(big.NewInt(11_000_000))
+	if !result {
+		t.Error("mantle token upgrade should used for testnet")
+	}
+
+	upgradeConfig = NewMantleUpgradeConfig(params.MantleTestnetChainID)
+	result = upgradeConfig.IsMantleToken(big.NewInt(11_000_001))
+	if result {
+		t.Error("mantle token upgrade height has passed")
+	}
+
+	upgradeConfig = NewMantleUpgradeConfig(params.MantleTestnetChainID)
+	result = upgradeConfig.IsMantleToken(big.NewInt(10_999_999))
+	if result {
+		t.Error("mantle token upgrade height does not reach to")
+	}
+}
+
+func TestConfig_IsEigenDa(t *testing.T) {
+	upgradeConfig := NewMantleUpgradeConfig(params.MantleMainnetChainID)
+	result := upgradeConfig.IsEigenDa(big.NewInt(8_280_000))
+	if result {
+		t.Error("eigen data layer upgrade could not used for mainnet")
+	}
+
+	upgradeConfig = NewMantleUpgradeConfig(params.MantleTestnetChainID)
+	result = upgradeConfig.IsEigenDa(big.NewInt(8_280_000))
+	if !result {
+		t.Error("eigen data layer upgrade should used for testnet")
+	}
+
+	upgradeConfig = NewMantleUpgradeConfig(params.MantleTestnetChainID)
+	result = upgradeConfig.IsEigenDa(big.NewInt(8_280_001))
+	if result {
+		t.Error("eigen data layer upgrade height has passed")
+	}
+
+	upgradeConfig = NewMantleUpgradeConfig(params.MantleTestnetChainID)
+	result = upgradeConfig.IsEigenDa(big.NewInt(8_279_999))
+	if result {
+		t.Error("eigen data layer upgrade height does not reach to")
+	}
+}
+
+func TestConfig_IsUpdateGasLimitBlock(t *testing.T) {
+	upgradeConfig := NewMantleUpgradeConfig(params.MantleMainnetChainID)
+	result := upgradeConfig.IsUpdateGasLimitBlock(big.NewInt(222_073))
+	if result {
+		t.Error("update gaslimit upgrade could not used for mainnet")
+	}
+
+	upgradeConfig = NewMantleUpgradeConfig(params.MantleTestnetChainID)
+	result = upgradeConfig.IsUpdateGasLimitBlock(big.NewInt(222_073))
+	if !result {
+		t.Error("update gaslimit upgrade should used for testnet")
+	}
+
+	upgradeConfig = NewMantleUpgradeConfig(params.MantleTestnetChainID)
+	result = upgradeConfig.IsUpdateGasLimitBlock(big.NewInt(222_074))
+	if !result {
+		t.Error("update gaslimit upgrade take effect after 222_073")
+	}
+
+	upgradeConfig = NewMantleUpgradeConfig(params.MantleTestnetChainID)
+	result = upgradeConfig.IsUpdateGasLimitBlock(big.NewInt(222_072))
+	if result {
+		t.Error("update gaslimit upgrade height does not reach to")
+	}
+}
diff --git a/packages/contracts/genesis/state-dump.latest.json b/packages/contracts/genesis/state-dump.latest.json
index 27d494150..4f522fdda 100644
--- a/packages/contracts/genesis/state-dump.latest.json
+++ b/packages/contracts/genesis/state-dump.latest.json
@@ -1,5 +1,5 @@
 {
-  "commit": "d627d242fe19f50f344f1ff4b27532d1757303a6",
+  "commit": "42caabb8f723304f038f9027178b3810672fc60c",
   "config": {
     "chainId": 17,
     "homesteadBlock": 0,