// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package params

import (
	"errors"
	"fmt"
	"math"
	"math/big"
	"sort"
	"strconv"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/params/forks"
)

// Genesis hashes to enforce below configs on.
var (
	MainnetGenesisHash    = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
	HoleskyGenesisHash    = common.HexToHash("0xb5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4")
	SepoliaGenesisHash    = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9")
	RinkebyGenesisHash    = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")
	GoerliGenesisHash     = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a")
	HoodiGenesisHash      = common.HexToHash("0xbbe312868b376a3001692a646dd2d7d1e4406380dfd86b98aa8a34d1557c971b")
	MumbaiGenesisHash     = common.HexToHash("0x7b66506a9ebdbf30d32b43c5f15a3b1216269a1ec3a75aa3182b86176a2b1ca7")
	BorMainnetGenesisHash = common.HexToHash("0xa9c28ce2141b56c474f1dc504bee9b01eb1bd7d1a507580d5519d4437a97de1b")
	KilnGenesisHash       = common.HexToHash("0x51c7fe41be669f69c45c33a56982cbde405313342d9e2b00d7c91a7b284dd4f8")
	AmoyGenesisHash       = common.HexToHash("0x7202b2b53c5a0836e773e319d18922cc756dd67432f9a1f65352b61f4406c697")
)

var (
	MainnetTerminalTotalDifficulty, _ = new(big.Int).SetString("58_750_000_000_000_000_000_000", 0)

	// Note: for "eth" based chains, all hardforks post merge are removed as they're timebased while
	// our configs are block based.

	// MainnetChainConfig is the chain parameters to run a node on the main network.
	MainnetChainConfig = &ChainConfig{
		ChainID:                 big.NewInt(1),
		HomesteadBlock:          big.NewInt(1_150_000),
		DAOForkBlock:            big.NewInt(1_920_000),
		DAOForkSupport:          true,
		EIP150Block:             big.NewInt(2_463_000),
		EIP155Block:             big.NewInt(2_675_000),
		EIP158Block:             big.NewInt(2_675_000),
		ByzantiumBlock:          big.NewInt(4_370_000),
		ConstantinopleBlock:     big.NewInt(7_280_000),
		PetersburgBlock:         big.NewInt(7_280_000),
		IstanbulBlock:           big.NewInt(9_069_000),
		MuirGlacierBlock:        big.NewInt(9_200_000),
		BerlinBlock:             big.NewInt(12_244_000),
		LondonBlock:             big.NewInt(12_965_000),
		ArrowGlacierBlock:       big.NewInt(13_773_000),
		GrayGlacierBlock:        big.NewInt(15_050_000),
		TerminalTotalDifficulty: MainnetTerminalTotalDifficulty, // 58_750_000_000_000_000_000_000
		DepositContractAddress:  common.HexToAddress("0x00000000219ab540356cbb839cbe05303d7705fa"),
		Ethash:                  new(EthashConfig),
	}
	// HoleskyChainConfig contains the chain parameters to run a node on the Holesky test network.
	HoleskyChainConfig = &ChainConfig{
		ChainID:                 big.NewInt(17000),
		HomesteadBlock:          big.NewInt(0),
		DAOForkBlock:            nil,
		DAOForkSupport:          true,
		EIP150Block:             big.NewInt(0),
		EIP155Block:             big.NewInt(0),
		EIP158Block:             big.NewInt(0),
		ByzantiumBlock:          big.NewInt(0),
		ConstantinopleBlock:     big.NewInt(0),
		PetersburgBlock:         big.NewInt(0),
		IstanbulBlock:           big.NewInt(0),
		MuirGlacierBlock:        nil,
		BerlinBlock:             big.NewInt(0),
		LondonBlock:             big.NewInt(0),
		ArrowGlacierBlock:       nil,
		GrayGlacierBlock:        nil,
		TerminalTotalDifficulty: big.NewInt(0),
		MergeNetsplitBlock:      nil,
		Ethash:                  new(EthashConfig),
	}
	// SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network.
	SepoliaChainConfig = &ChainConfig{
		ChainID:                 big.NewInt(11155111),
		HomesteadBlock:          big.NewInt(0),
		DAOForkBlock:            nil,
		DAOForkSupport:          true,
		EIP150Block:             big.NewInt(0),
		EIP155Block:             big.NewInt(0),
		EIP158Block:             big.NewInt(0),
		ByzantiumBlock:          big.NewInt(0),
		ConstantinopleBlock:     big.NewInt(0),
		PetersburgBlock:         big.NewInt(0),
		IstanbulBlock:           big.NewInt(0),
		MuirGlacierBlock:        big.NewInt(0),
		BerlinBlock:             big.NewInt(0),
		LondonBlock:             big.NewInt(0),
		ArrowGlacierBlock:       nil,
		GrayGlacierBlock:        nil,
		TerminalTotalDifficulty: big.NewInt(17_000_000_000_000_000),
		MergeNetsplitBlock:      big.NewInt(1735371),
		Ethash:                  new(EthashConfig),
	}
	// HoodiChainConfig contains the chain parameters to run a node on the Hoodi test network.
	HoodiChainConfig = &ChainConfig{
		ChainID:                 big.NewInt(560048),
		HomesteadBlock:          big.NewInt(0),
		DAOForkBlock:            nil,
		DAOForkSupport:          true,
		EIP150Block:             big.NewInt(0),
		EIP155Block:             big.NewInt(0),
		EIP158Block:             big.NewInt(0),
		ByzantiumBlock:          big.NewInt(0),
		ConstantinopleBlock:     big.NewInt(0),
		PetersburgBlock:         big.NewInt(0),
		IstanbulBlock:           big.NewInt(0),
		MuirGlacierBlock:        big.NewInt(0),
		BerlinBlock:             big.NewInt(0),
		LondonBlock:             big.NewInt(0),
		ArrowGlacierBlock:       nil,
		GrayGlacierBlock:        nil,
		TerminalTotalDifficulty: big.NewInt(0),
		MergeNetsplitBlock:      big.NewInt(0),
		Ethash:                  new(EthashConfig),
	}
	// GoerliChainConfig contains the chain parameters to run a node on the Görli test network.
	GoerliChainConfig = &ChainConfig{
		ChainID:                 big.NewInt(5),
		HomesteadBlock:          big.NewInt(0),
		DAOForkBlock:            nil,
		DAOForkSupport:          true,
		EIP150Block:             big.NewInt(0),
		EIP155Block:             big.NewInt(0),
		EIP158Block:             big.NewInt(0),
		ByzantiumBlock:          big.NewInt(0),
		ConstantinopleBlock:     big.NewInt(0),
		PetersburgBlock:         big.NewInt(0),
		IstanbulBlock:           big.NewInt(1_561_651),
		MuirGlacierBlock:        nil,
		BerlinBlock:             big.NewInt(4_460_644),
		LondonBlock:             big.NewInt(5_062_605),
		ArrowGlacierBlock:       nil,
		TerminalTotalDifficulty: big.NewInt(10_790_000),
		Clique: &CliqueConfig{
			Period: 15,
			Epoch:  30000,
		},
	}

	// BorTestChainConfig contains the chain parameters to run a node on the Test network.
	BorTestChainConfig = &ChainConfig{
		ChainID:             big.NewInt(80002),
		HomesteadBlock:      big.NewInt(0),
		DAOForkBlock:        nil,
		DAOForkSupport:      true,
		EIP150Block:         big.NewInt(0),
		EIP155Block:         big.NewInt(0),
		EIP158Block:         big.NewInt(0),
		ByzantiumBlock:      big.NewInt(0),
		ConstantinopleBlock: big.NewInt(0),
		PetersburgBlock:     big.NewInt(0),
		IstanbulBlock:       big.NewInt(0),
		MuirGlacierBlock:    big.NewInt(0),
		BerlinBlock:         big.NewInt(0),
		LondonBlock:         big.NewInt(0),
		Bor: &BorConfig{
			Period: map[string]uint64{
				"0": 2,
			},
			ProducerDelay: map[string]uint64{
				"0": 6,
			},
			Sprint: map[string]uint64{
				"0": 64,
			},
			BackupMultiplier: map[string]uint64{
				"0": 2,
			},
			ValidatorContract:     "0x0000000000000000000000000000000000001000",
			StateReceiverContract: "0x0000000000000000000000000000000000001001",
			BurntContract: map[string]string{
				"0": "0x00000000000000000000000000000000000000000",
			},
		},
		ShanghaiBlock: big.NewInt(0),
		CancunBlock:   big.NewInt(0),
	}
	BorUnittestChainConfig = &ChainConfig{
		ChainID:             big.NewInt(80003),
		HomesteadBlock:      big.NewInt(0),
		DAOForkBlock:        nil,
		DAOForkSupport:      true,
		EIP150Block:         big.NewInt(0),
		EIP155Block:         big.NewInt(0),
		EIP158Block:         big.NewInt(0),
		ByzantiumBlock:      big.NewInt(0),
		ConstantinopleBlock: big.NewInt(0),
		PetersburgBlock:     big.NewInt(0),
		IstanbulBlock:       big.NewInt(0),
		MuirGlacierBlock:    big.NewInt(0),
		BerlinBlock:         big.NewInt(0),
		LondonBlock:         big.NewInt(0),
		Bor: &BorConfig{
			Period: map[string]uint64{
				"0": 1,
			},
			ProducerDelay: map[string]uint64{
				"0": 3,
			},
			Sprint: map[string]uint64{
				"0": 32,
			},
			BackupMultiplier: map[string]uint64{
				"0": 2,
			},
			Coinbase: map[string]string{
				"0": "0x000000000000000000000000000000000000ba5e",
			},
			ValidatorContract:     "0x0000000000000000000000000000000000001000",
			StateReceiverContract: "0x0000000000000000000000000000000000001001",
			BurntContract: map[string]string{
				"0": "0x00000000000000000000000000000000000000000",
			},
		},
	}

	// MumbaiChainConfig contains the chain parameters to run a node on the Mumbai test network.
	MumbaiChainConfig = &ChainConfig{
		ChainID:             big.NewInt(80001),
		HomesteadBlock:      big.NewInt(0),
		DAOForkBlock:        nil,
		DAOForkSupport:      true,
		EIP150Block:         big.NewInt(0),
		EIP155Block:         big.NewInt(0),
		EIP158Block:         big.NewInt(0),
		ByzantiumBlock:      big.NewInt(0),
		ConstantinopleBlock: big.NewInt(0),
		PetersburgBlock:     big.NewInt(0),
		IstanbulBlock:       big.NewInt(2722000),
		MuirGlacierBlock:    big.NewInt(2722000),
		BerlinBlock:         big.NewInt(13996000),
		LondonBlock:         big.NewInt(22640000),
		ShanghaiBlock:       big.NewInt(41874000),
		CancunBlock:         big.NewInt(45648608),
		PragueBlock:         big.NewInt(48467456),
		Bor: &BorConfig{
			JaipurBlock:    big.NewInt(22770000),
			DelhiBlock:     big.NewInt(29638656),
			IndoreBlock:    big.NewInt(37075456),
			AhmedabadBlock: big.NewInt(48467456),
			BhilaiBlock:    big.NewInt(48467456),
			RioBlock:       big.NewInt(48473856),
			StateSyncConfirmationDelay: map[string]uint64{
				"37075456": 128,
			},
			Period: map[string]uint64{
				"0":        2,
				"25275000": 5,
				"29638656": 2,
			},
			ProducerDelay: map[string]uint64{
				"0":        6,
				"29638656": 4,
			},
			Sprint: map[string]uint64{
				"0":        64,
				"29638656": 16,
			},
			BackupMultiplier: map[string]uint64{
				"0":        2,
				"25275000": 5,
				"29638656": 2,
			},
			ValidatorContract:     "0x0000000000000000000000000000000000001000",
			StateReceiverContract: "0x0000000000000000000000000000000000001001",
			BurntContract: map[string]string{
				"22640000": "0x70bcA57F4579f58670aB2d18Ef16e02C17553C38",
				"41874000": "0x617b94CCCC2511808A3C9478ebb96f455CF167aA",
			},
			Coinbase: map[string]string{
				"0":        "0x0000000000000000000000000000000000000000",
				"49439808": "0x7Ee41D8A25641000661B1EF5E6AE8A00400466B0",
			},
			BlockAlloc: map[string]interface{}{
				// write as interface since that is how it is decoded in genesis
				"22244000": map[string]interface{}{
					"0000000000000000000000000000000000001010": map[string]interface{}{
						"balance": "0x0",
						"code":    "0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610caa565b005b3480156103eb57600080fd5b506103f4610dfc565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e05565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fc1565b005b3480156104e857600080fd5b506104f1611090565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b506105486110b6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110dc565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b506106046110fd565b005b34801561061257600080fd5b5061061b6111cd565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506111d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b50610758611358565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af611381565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de6113d8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e611411565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061144e565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b50610964611474565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b8101908080359060200190929190505050611501565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050611521565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a65611541565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a90611548565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb61154e565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115db565b005b348015610b2e57600080fd5b50610b376115f8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b60006040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b60003390506000610cba826110dc565b9050610cd18360065461161e90919063ffffffff16565b600681905550600083118015610ce657508234145b610d58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610dd4876110dc565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610e0d611381565b610e1657600080fd5b600081118015610e535750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b610ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611da96023913960400191505060405180910390fd5b6000610eb3836110dc565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015610f00573d6000803e3d6000fd5b50610f168360065461163e90919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f68585610f98896110dc565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611027576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611d866023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061108c8261165d565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b611105611381565b61110e57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b60008060008060418551146111ee5760009350505050611352565b602085015192506040850151915060ff6041860151169050601b8160ff16101561121957601b810190505b601b8160ff16141580156112315750601c8160ff1614155b156112425760009350505050611352565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561129f573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561134e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600381526020017f013881000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b6000813414611460576000905061146e565b61146b338484611755565b90505b92915050565b6040518060800160405280605b8152602001611e1e605b91396040516020018082805190602001908083835b602083106114c357805182526020820191506020810190506020830392506114a0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061153761153286868686611b12565b611be8565b9050949350505050565b6201388181565b60015481565b604051806080016040528060528152602001611dcc605291396040516020018082805190602001908083835b6020831061159d578051825260208201915060208101905060208303925061157a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b6115e3611381565b6115ec57600080fd5b6115f58161165d565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282111561162d57600080fd5b600082840390508091505092915050565b60008082840190508381101561165357600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561169757600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117d557600080fd5b505afa1580156117e9573d6000803e3d6000fd5b505050506040513d60208110156117ff57600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561189157600080fd5b505afa1580156118a5573d6000803e3d6000fd5b505050506040513d60208110156118bb57600080fd5b810190808051906020019092919050505090506118d9868686611c32565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156119e157600080fd5b505afa1580156119f5573d6000803e3d6000fd5b505050506040513d6020811015611a0b57600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a9957600080fd5b505afa158015611aad573d6000803e3d6000fd5b505050506040513d6020811015611ac357600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b6000806040518060800160405280605b8152602001611e1e605b91396040516020018082805190602001908083835b60208310611b645780518252602082019150602081019050602083039250611b41565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611cd4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f63616e27742073656e6420746f204d524332300000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611d1a573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a72315820ccd6c2a9c259832bbb367986ee06cd87af23022681b0cb22311a864b701d939564736f6c63430005100032",
					},
				},
				"41874000": map[string]interface{}{
					"0x0000000000000000000000000000000000001001": map[string]interface{}{
						"balance": "0x0",
						"code":    "0x608060405234801561001057600080fd5b506004361061005e576000357c01000000000000000000000000000000000000000000000000000000009004806319494a17146100635780633434735f146100fe5780635407ca6714610148575b600080fd5b6100e46004803603604081101561007957600080fd5b8101908080359060200190929190803590602001906401000000008111156100a057600080fd5b8201836020820111156100b257600080fd5b803590602001918460018302840111640100000000831117156100d457600080fd5b9091929391929390505050610166565b604051808215151515815260200191505060405180910390f35b6101066104d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101506104eb565b6040518082815260200191505060405180910390f35b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461021d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f742053797374656d2041646465737321000000000000000000000000000081525060200191505060405180910390fd5b606061027461026f85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506104f1565b61051f565b905060006102958260008151811061028857fe5b60200260200101516105fc565b90508060016000540114610311576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f537461746549647320617265206e6f742073657175656e7469616c000000000081525060200191505060405180910390fd5b600080815480929190600101919050555060006103418360018151811061033457fe5b602002602001015161066d565b905060606103628460028151811061035557fe5b6020026020010151610690565b905061036d8261071c565b156104c8576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103c75780820151818401526020810190506103ac565b50505050905090810190601f1680156103f45780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040527f26c53bea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008082516020840160008887f19650847f5a22725590b0a51c923940223f7458512164b1113359a735e86e7f27f44791ee88604051808215151515815260200191505060405180910390a250505b505050509392505050565b73fffffffffffffffffffffffffffffffffffffffe81565b60005481565b6104f961099c565b600060208301905060405180604001604052808451815260200182815250915050919050565b606061052a82610735565b61053357600080fd5b600061053e83610783565b905060608160405190808252806020026020018201604052801561057c57816020015b6105696109b6565b8152602001906001900390816105615790505b509050600061058e85602001516107f4565b8560200151019050600080600090505b848110156105ef576105af8361087d565b91506040518060400160405280838152602001848152508482815181106105d257fe5b60200260200101819052508183019250808060010191505061059e565b5082945050505050919050565b600080826000015111801561061657506021826000015111155b61061f57600080fd5b600061062e83602001516107f4565b9050600081846000015103905060008083866020015101905080519150602083101561066157826020036101000a820491505b81945050505050919050565b6000601582600001511461068057600080fd5b610689826105fc565b9050919050565b606060008260000151116106a357600080fd5b60006106b283602001516107f4565b905060008184600001510390506060816040519080825280601f01601f1916602001820160405280156106f45781602001600182028038833980820191505090505b5090506000816020019050610710848760200151018285610935565b81945050505050919050565b600080823b905060008163ffffffff1611915050919050565b6000808260000151141561074c576000905061077e565b60008083602001519050805160001a915060c060ff168260ff1610156107775760009250505061077e565b6001925050505b919050565b6000808260000151141561079a57600090506107ef565b600080905060006107ae84602001516107f4565b84602001510190506000846000015185602001510190505b808210156107e8576107d78261087d565b8201915082806001019350506107c6565b8293505050505b919050565b600080825160001a9050608060ff16811015610814576000915050610878565b60b860ff16811080610839575060c060ff168110158015610838575060f860ff1681105b5b15610848576001915050610878565b60c060ff168110156108685760018060b80360ff16820301915050610878565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561089e576001915061092b565b60b860ff168110156108bb576001608060ff16820301915061092a565b60c060ff168110156108eb5760b78103600185019450806020036101000a85510460018201810193505050610929565b60f860ff1681101561090857600160c060ff168203019150610928565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b600081141561094357610997565b5b602060ff1681106109735782518252602060ff1683019250602060ff1682019150602060ff1681039050610944565b6000600182602060ff16036101000a03905080198451168184511681811785525050505b505050565b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200160008152509056fea265627a7a723158208f1ea6fcf63d6911ac5dbfe340be1029614581802c6a750e7d6354b32ce6647c64736f6c63430005110032",
					},
				},
			},
		},
	}

	// AmoyChainConfig contains the chain parameters to run a node on the Amoy test network.
	AmoyChainConfig = &ChainConfig{
		ChainID:             big.NewInt(80002),
		HomesteadBlock:      big.NewInt(0),
		DAOForkBlock:        nil,
		DAOForkSupport:      true,
		EIP150Block:         big.NewInt(0),
		EIP155Block:         big.NewInt(0),
		EIP158Block:         big.NewInt(0),
		ByzantiumBlock:      big.NewInt(0),
		ConstantinopleBlock: big.NewInt(0),
		PetersburgBlock:     big.NewInt(0),
		IstanbulBlock:       big.NewInt(0),
		MuirGlacierBlock:    big.NewInt(0),
		BerlinBlock:         big.NewInt(0),
		LondonBlock:         big.NewInt(73100),
		ShanghaiBlock:       big.NewInt(73100),
		CancunBlock:         big.NewInt(5423600),
		PragueBlock:         big.NewInt(22765056),
		Bor: &BorConfig{
			JaipurBlock:    big.NewInt(73100),
			DelhiBlock:     big.NewInt(73100),
			IndoreBlock:    big.NewInt(73100),
			AhmedabadBlock: big.NewInt(11865856),
			BhilaiBlock:    big.NewInt(22765056),
			RioBlock:       big.NewInt(26272256),
			StateSyncConfirmationDelay: map[string]uint64{
				"0": 128,
			},
			Period: map[string]uint64{
				"0": 2,
			},
			ProducerDelay: map[string]uint64{
				"0": 4,
			},
			Sprint: map[string]uint64{
				"0": 16,
			},
			BackupMultiplier: map[string]uint64{
				"0": 2,
			},
			ValidatorContract:     "0x0000000000000000000000000000000000001000",
			StateReceiverContract: "0x0000000000000000000000000000000000001001",
			OverrideStateSyncRecordsInRange: []BlockRangeOverride{
				{StartBlock: 23184305, EndBlock: 23220127, Value: 0},
			},
			BurntContract: map[string]string{
				"0":     "0x000000000000000000000000000000000000dead",
				"73100": "0xeCDD77cE6f146cCf5dab707941d318Bd50eeD2C9",
			},
			Coinbase: map[string]string{
				"0":        "0x0000000000000000000000000000000000000000",
				"26272256": "0x7Ee41D8A25641000661B1EF5E6AE8A00400466B0",
			},
			SkipValidatorByteCheck: []uint64{26160367, 26161087, 26171567, 26173743, 26175647},
			BlockAlloc: map[string]interface{}{
				// write as interface since that is how it is decoded in genesis
				"11865856": map[string]interface{}{
					"0000000000000000000000000000000000001001": map[string]interface{}{
						"balance": "0x0",
						"code":    "0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635407ca671161008c578063abca220411610066578063abca2204146102fa578063d72a0b6714610302578063ee3a87f21461031f578063f165053614610342576100cf565b80635407ca67146102585780636757e5d914610260578063942af179146102f2576100cf565b806303112a17146100d457806319494a17146100f357806330e69fc31461017e578063318926f7146101985780633434735f146101bc57806351950cd9146101c4575b600080fd5b6100f1600480360360208110156100ea57600080fd5b503561034a565b005b61016a6004803603604081101561010957600080fd5b8135919081019060408101602082013564010000000081111561012b57600080fd5b82018360208201111561013d57600080fd5b8035906020019184600183028401116401000000008311171561015f57600080fd5b50909250905061060d565b604080519115158252519081900360200190f35b61018661093e565b60408051918252519081900360200190f35b6101a0610944565b604080516001600160a01b039092168252519081900360200190f35b6101a0610968565b6100f160048036036102808110156101db57600080fd5b61020082013590610220830135906001600160a01b036102408501351690840184610280810161026082013564010000000081111561021957600080fd5b82018360208201111561022b57600080fd5b8035906020019184600183028401116401000000008311171561024d57600080fd5b509092509050610973565b610186610c78565b61027d6004803603602081101561027657600080fd5b5035610c7e565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102b757818101518382015260200161029f565b50505050905090810190601f1680156102e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610186610d19565b610186610d1f565b61016a6004803603602081101561031857600080fd5b5035610d25565b6100f16004803603604081101561033557600080fd5b5080359060200135610d3a565b610186610db0565b60008181526003602090815260409182902080548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452606093928301828280156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b50505050509050805160001415610426576040805162461bcd60e51b815260206004820152600660248201526508599bdd5b9960d21b604482015290519081900360640190fd5b600082815260036020526040812061043d916112bb565b6000606082806020019051604081101561045657600080fd5b81516020830180516040519294929383019291908464010000000082111561047d57600080fd5b90830190602082018581111561049257600080fd5b82516401000000008111828201881017156104ac57600080fd5b82525081516020918201929091019080838360005b838110156104d95781810151838201526020016104c1565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b5060405250505091509150837f8797144948782adcede8e04bfa0bd8fd56941e0df7508bd02a629b477f7b073a60405160405180910390a2604080516313629df560e11b815260048101868152602482019283528351604483015283516001600160a01b038616936326c53bea938993879390929160640190602085019080838360005b838110156105a257818101518382015260200161058a565b50505050905090810190601f1680156105cf5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156105ef57600080fd5b505af1158015610603573d6000803e3d6000fd5b5050505050505050565b6000336002600160a01b031461065f576040805162461bcd60e51b81526020600482015260126024820152714e6f742053797374656d204164646573732160701b604482015290519081900360640190fd5b60606106a86106a385858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610db592505050565b610ddb565b905060006106c9826000815181106106bc57fe5b6020026020010151610f14565b90508060005460010114610724576040805162461bcd60e51b815260206004820152601b60248201527f537461746549647320617265206e6f742073657175656e7469616c0000000000604482015290519081900360640190fd5b6000805460019081018255835161074c918591811061073f57fe5b6020026020010151610f62565b9050606061076d8460028151811061076057fe5b6020026020010151610f82565b905061077882610fff565b15610933576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107cf5781810151838201526020016107b7565b50505050905090810190601f1680156107fc5780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529190526020810180516001600160e01b03166313629df560e11b1781528151919650600095508594509092509050828887f1604080518215158152905191985086917f5a22725590b0a51c923940223f7458512164b1113359a735e86e7f27f44791ee9181900360200190a28661093057838360405160200180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108cc5781810151838201526020016108b4565b50505050905090810190601f1680156108f95780820380516001836020036101000a031916815260200191505b5060408051601f1981840301815291815260008b815260036020908152919020825161092e9750909550910192509050611302565b505b50505b505050509392505050565b60045481565b7f000000000000000000000000be971fef2bb60f709e1daf3e55d00914e230cd9481565b6002600160a01b0381565b6201000085106109be576040805162461bcd60e51b81526020600482015260116024820152700d2dcecc2d8d2c840d8cac2cc92dcc8caf607b1b604482015290519081900360640190fd5b60045460058054600101908190551115610a05576040805162461bcd60e51b8152602060048201526003602482015262195b9960ea1b604482015290519081900360640190fd5b60015480610a42576040805162461bcd60e51b8152602060048201526005602482015264085c9bdbdd60da1b604482015290519081900360640190fd5b60008585858560405160200180858152602001846001600160a01b0316815260200180602001828103825284848281815260200192508082843760008184015260408051601f19601f909301831690940184810390920184525250805160209091012096507f28cf91ac064e179f8a42e4b7a20ba080187781da55fd4f3f18870b7a25bacb559550505050828414801592509050610aef575060008281526002602052604090205460ff16155b610b29576040805162461bcd60e51b815260206004808301919091526024820152631d5cd95960e21b604482015290519081900360640190fd5b60008281526002602052604090819020805460ff191660011790558051610200818101909252610b74918b9060109083908390808284376000920191909152508b915085905061100b565b8314610bb0576040805162461bcd60e51b815260206004820152600660248201526510b83937b7b360d11b604482015290519081900360640190fd5b60405187907f8797144948782adcede8e04bfa0bd8fd56941e0df7508bd02a629b477f7b073a90600090a2604080516313629df560e11b81526004810189815260248201928352604482018790526001600160a01b038916926326c53bea928b928a928a92606401848480828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b158015610c5557600080fd5b505af1158015610c69573d6000803e3d6000fd5b50505050505050505050505050565b60005481565b60036020908152600091825260409182902080548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084529091830182828015610d115780601f10610ce657610100808354040283529160200191610d11565b820191906000526020600020905b815481529060010190602001808311610cf457829003601f168201915b505050505081565b60055481565b60015481565b60026020526000908152604090205460ff1681565b336001600160a01b037f000000000000000000000000be971fef2bb60f709e1daf3e55d00914e230cd941614610da5576040805162461bcd60e51b815260206004820152600b60248201526a10b937b7ba29b2ba3a32b960a91b604482015290519081900360640190fd5b600191909155600455565b601081565b610dbd611380565b5060408051808201909152815181526020828101908201525b919050565b6060610de6826110b6565b610def57600080fd5b6000610dfa836110f0565b905060608167ffffffffffffffff81118015610e1557600080fd5b50604051908082528060200260200182016040528015610e4f57816020015b610e3c611380565b815260200190600190039081610e345790505b5090506000610e618560200151611148565b60208601510190506000805b84811015610eb857610e7e836111ab565b9150604051806040016040528083815260200184815250848281518110610ea157fe5b602090810291909101015291810191600101610e6d565b5085516020870151830314610f0a576040805162461bcd60e51b81526020600482015260136024820152722bb937b733903a37ba30b6103632b733ba341760691b604482015290519081900360640190fd5b5090949350505050565b805160009015801590610f2957508151602110155b610f3257600080fd5b600080610f3e84611244565b815191935091506020821015610f5a5760208290036101000a90045b949350505050565b8051600090601514610f7357600080fd5b610f7c82610f14565b92915050565b8051606090610f9057600080fd5b600080610f9c84611244565b9150915060608167ffffffffffffffff81118015610fb957600080fd5b506040519080825280601f01601f191660200182016040528015610fe4576020820181803683370190505b50905060208101610ff684828561126a565b50949350505050565b3b63ffffffff16151590565b600081815b6010811015610ff657600185821c8116141561106c5785816010811061103257fe5b60200201518260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091506110ae565b8186826010811061107957fe5b602002015160405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091505b600101611010565b80516000906110c757506000610dd6565b6020820151805160001a9060c08210156110e657600092505050610dd6565b5060019392505050565b805160009061110157506000610dd6565b6000806111118460200151611148565b602085015185519181019250015b8082101561113f57611130826111ab565b6001909301929091019061111f565b50909392505050565b8051600090811a6080811015611162576000915050610dd6565b60b881108061117d575060c0811080159061117d575060f881105b1561118c576001915050610dd6565b60c08110156111a05760b519019050610dd6565b60f519019050610dd6565b80516000908190811a60808110156111c6576001915061123d565b60b88110156111db57607e198101915061123d565b60c08110156112085760b78103600185019450806020036101000a8551046001820181019350505061123d565b60f881101561121d5760be198101915061123d565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60008060006112568460200151611148565b602085015194519481019594039392505050565b80611274576112b6565b5b60208110611294578251825260209283019290910190601f1901611275565b80156112b6578251825160208390036101000a60001901801990921691161782525b505050565b50805460018160011615610100020316600290046000825580601f106112e157506112ff565b601f0160209004906000526020600020908101906112ff919061139a565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061134357805160ff1916838001178555611370565b82800160010185558215611370579182015b82811115611370578251825591602001919060010190611355565b5061137c92915061139a565b5090565b604051806040016040528060008152602001600081525090565b5b8082111561137c576000815560010161139b56fea164736f6c634300060c000a",
					},
					"0000000000000000000000000000000000001010": map[string]interface{}{
						"balance": "0x0",
						"code":    "0x6080604052600436106101b75760003560e01c80638da5cb5b116100ec578063b789543c1161008a578063e614d0d611610064578063e614d0d614610695578063ed9ef524146106aa578063f2fde38b146106dd578063fc0c546a14610710576101b7565b8063b789543c14610626578063cc79f97b1461066b578063e306f77914610680576101b7565b806395d89b41116100c657806395d89b41146105a6578063a9059cbb146105bb578063abceeba2146105e7578063acd06cb3146105fc576101b7565b80638da5cb5b146105535780638f32d59b146105685780639025e64c14610591576101b7565b806347e7ef241161015957806370a082311161013357806370a082311461043c578063715018a61461046f578063771282f61461048457806377d32e9414610499576101b7565b806347e7ef24146103b3578063485cc955146103ec57806360f96a8f14610427576101b7565b806319d27d9c1161019557806319d27d9c146102a25780632e1a7d4d14610356578063313ce5671461037357806342fc47fb1461039e576101b7565b806306fdde03146101bc5780631499c5921461024657806318160ddd1461027b575b600080fd5b3480156101c857600080fd5b506101d1610725565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561020b5781810151838201526020016101f3565b50505050905090810190601f1680156102385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025257600080fd5b506102796004803603602081101561026957600080fd5b50356001600160a01b031661075c565b005b34801561028757600080fd5b5061029061079c565b60408051918252519081900360200190f35b3480156102ae57600080fd5b5061033a600480360360a08110156102c557600080fd5b8101906020810181356401000000008111156102e057600080fd5b8201836020820111156102f257600080fd5b8035906020019184600183028401116401000000008311171561031457600080fd5b9193509150803590602081013590604081013590606001356001600160a01b03166107ac565b604080516001600160a01b039092168252519081900360200190f35b6102796004803603602081101561036c57600080fd5b50356107ee565b34801561037f57600080fd5b506103886108c6565b6040805160ff9092168252519081900360200190f35b3480156103aa57600080fd5b5061033a6108cb565b3480156103bf57600080fd5b50610279600480360360408110156103d657600080fd5b506001600160a01b0381351690602001356108da565b3480156103f857600080fd5b506102796004803603604081101561040f57600080fd5b506001600160a01b03813581169160200135166109a8565b34801561043357600080fd5b5061033a610a21565b34801561044857600080fd5b506102906004803603602081101561045f57600080fd5b50356001600160a01b0316610a30565b34801561047b57600080fd5b50610279610a3d565b34801561049057600080fd5b50610290610a98565b3480156104a557600080fd5b5061033a600480360360408110156104bc57600080fd5b813591908101906040810160208201356401000000008111156104de57600080fd5b8201836020820111156104f057600080fd5b8035906020019184600183028401116401000000008311171561051257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610a9e945050505050565b34801561055f57600080fd5b5061033a610bc2565b34801561057457600080fd5b5061057d610bd1565b604080519115158252519081900360200190f35b34801561059d57600080fd5b506101d1610be2565b3480156105b257600080fd5b506101d1610c00565b61057d600480360360408110156105d157600080fd5b506001600160a01b038135169060200135610c1d565b3480156105f357600080fd5b50610290610c40565b34801561060857600080fd5b5061057d6004803603602081101561061f57600080fd5b5035610cc9565b34801561063257600080fd5b506102906004803603608081101561064957600080fd5b506001600160a01b038135169060208101359060408101359060600135610cde565b34801561067757600080fd5b50610290610cfd565b34801561068c57600080fd5b50610290610d03565b3480156106a157600080fd5b50610290610d09565b3480156106b657600080fd5b50610279600480360360208110156106cd57600080fd5b50356001600160a01b0316610d53565b3480156106e957600080fd5b506102796004803603602081101561070057600080fd5b50356001600160a01b0316610e05565b34801561071c57600080fd5b5061033a610e22565b60408051808201909152601781527f506f6c79676f6e2045636f73797374656d20546f6b656e000000000000000000602082015290565b6040805162461bcd60e51b815260206004820152601060248201526f44697361626c6564206665617475726560801b604482015290519081900360640190fd5b6b204fce5e3e2502611000000090565b6040805162461bcd60e51b815260206004820152601060248201526f44697361626c6564206665617475726560801b6044820152905160009181900360640190fd5b3360006107fa82610a30565b600654909150610810908463ffffffff610e3116565b600655821580159061082157508234145b610868576040805162461bcd60e51b8152602060048201526013602482015272125b9cdd59999a58da595b9d08185b5bdd5b9d606a1b604482015290519081900360640190fd5b6002546001600160a01b0380841691167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f85846108a487610a30565b60408051938452602084019290925282820152519081900360600190a3505050565b601290565b6003546001600160a01b031681565b6108e2610bd1565b6108eb57600080fd5b60008111801561090357506001600160a01b03821615155b61093e5760405162461bcd60e51b815260040180806020018281038252602381526020018061138d6023913960400191505060405180910390fd5b600061094983610a30565b60065490915061095f908363ffffffff610e4616565b60065561096c8383610e58565b6002546001600160a01b0380851691167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f684846108a488610a30565b60075460ff16156109ea5760405162461bcd60e51b815260040180806020018281038252602381526020018061136a6023913960400191505060405180910390fd5b6007805460ff19166001179055600280546001600160a01b0383166001600160a01b0319909116179055610a1d82610f17565b5050565b6004546001600160a01b031681565b6001600160a01b03163190565b610a45610bd1565b610a4e57600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60065481565b6000806000808451604114610ab95760009350505050610bbc565b50505060208201516040830151604184015160ff16601b811015610adb57601b015b8060ff16601b14158015610af357508060ff16601c14155b15610b045760009350505050610bbc565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa158015610b5b573d6000803e3d6000fd5b5050604051601f1901519450506001600160a01b038416610bb8576040805162461bcd60e51b815260206004820152601260248201527122b93937b91034b71032b1b932b1b7bb32b960711b604482015290519081900360640190fd5b5050505b92915050565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b604051806040016040528060028152602001613a9960f01b81525081565b6040805180820190915260038152621413d360ea1b602082015290565b6000813414610c2e57506000610bbc565b610c39338484610f85565b9392505050565b6040518060800160405280605b8152602001611434605b91396040516020018082805190602001908083835b60208310610c8b5780518252601f199092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020526000908152604090205460ff1681565b6000610cf4610cef868686866111d2565b61128b565b95945050505050565b613a9981565b60015481565b6040518060800160405280605281526020016113b06052913960405160200180828051906020019080838360208310610c8b5780518252601f199092019160209182019101610c6c565b610d5b610bd1565b610d6457600080fd5b6001600160a01b038116610da95760405162461bcd60e51b81526004018080602001828103825260328152602001806114026032913960400191505060405180910390fd5b6003546040516001600160a01b038084169216907f1f9f3556dd336016cdf20adaead7d5c73665dba664b60e8c17e9a4eb91ce1d3990600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b610e0d610bd1565b610e1657600080fd5b610e1f81610f17565b50565b6002546001600160a01b031681565b600082821115610e4057600080fd5b50900390565b600082820183811015610c3957600080fd5b60085415610e9a576040805162461bcd60e51b815260206004820152600a6024820152697265656e7472616e637960b01b604482015290519081900360640190fd5b6001600855604051611388906000906060906001600160a01b038616908490869085818181858888f193505050503d8060008114610ef4576040519150601f19603f3d011682016040523d82523d6000602084013e610ef9565b606091505b509150915081610f0b57805160208201fd5b50506000600855505050565b6001600160a01b038116610f2a57600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516370a0823160e01b81526001600160a01b03851660048201529051600091829130916370a08231916024808301926020929190829003018186803b158015610fd057600080fd5b505afa158015610fe4573d6000803e3d6000fd5b505050506040513d6020811015610ffa57600080fd5b5051604080516370a0823160e01b81526001600160a01b0387166004820152905191925060009130916370a08231916024808301926020929190829003018186803b15801561104857600080fd5b505afa15801561105c573d6000803e3d6000fd5b505050506040513d602081101561107257600080fd5b50519050611081868686611299565b600254604080516370a0823160e01b81526001600160a01b03898116600483018190529251818a1694909116917fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c49189918891889130916370a0823191602480820192602092909190829003018186803b1580156110fe57600080fd5b505afa158015611112573d6000803e3d6000fd5b505050506040513d602081101561112857600080fd5b5051604080516370a0823160e01b81526001600160a01b038f166004820152905130916370a08231916024808301926020929190829003018186803b15801561117057600080fd5b505afa158015611184573d6000803e3d6000fd5b505050506040513d602081101561119a57600080fd5b50516040805195865260208601949094528484019290925260608401526080830152519081900360a00190a450600195945050505050565b6000806040518060800160405280605b8152602001611434605b91396040516020018082805190602001908083835b602083106112205780518252601f199092019160209182019101611201565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835280855282519282019290922082526001600160a01b039b909b169a81019a909a5250880196909652505050606084019190915260808301525060a0902090565b6000610bbc82600154611347565b6001600160a01b0382163014156112ed576040805162461bcd60e51b8152602060048201526013602482015272063616e27742073656e6420746f204d5243323606c1b604482015290519081900360640190fd5b6112f78282610e58565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b60405161190160f01b815260028101919091526022810191909152604290209056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e7472616374294368696c6420746f6b656e3a206e6577206368696c64206164647265737320697320746865207a65726f2061646472657373546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a723158205f23be7574e70cfc01d0cfd6803b871f92465e9ae4a10fe95ed31ccb810bda3e64736f6c63430005110032",
					},
					"360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9": map[string]interface{}{
						"balance": "0x0",
						"code":    "0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b9578063095ea7b31461014957806318160ddd146101ae57806323b872dd146101d95780632e1a7d4d1461025e578063313ce5671461028b57806370a08231146102bc57806395d89b4114610313578063a9059cbb146103a3578063d0e30db014610408578063dd62ed3e14610412575b6100b7610489565b005b3480156100c557600080fd5b506100ce610526565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010e5780820151818401526020810190506100f3565b50505050905090810190601f16801561013b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015557600080fd5b50610194600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105c4565b604051808215151515815260200191505060405180910390f35b3480156101ba57600080fd5b506101c36106b6565b6040518082815260200191505060405180910390f35b3480156101e557600080fd5b50610244600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506106d5565b604051808215151515815260200191505060405180910390f35b34801561026a57600080fd5b5061028960048036038101908080359060200190929190505050610a22565b005b34801561029757600080fd5b506102a0610b55565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102c857600080fd5b506102fd600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b68565b6040518082815260200191505060405180910390f35b34801561031f57600080fd5b50610328610b80565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036857808201518184015260208101905061034d565b50505050905090810190601f1680156103955780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103af57600080fd5b506103ee600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c1e565b604051808215151515815260200191505060405180910390f35b610410610489565b005b34801561041e57600080fd5b50610473600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c33565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105bc5780601f10610591576101008083540402835291602001916105bc565b820191906000526020600020905b81548152906001019060200180831161059f57829003601f168201915b505050505081565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561072557600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141580156107fd57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156109185781600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561088d57600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a7057600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610b03573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b600260009054906101000a900460ff1681565b60036020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c165780601f10610beb57610100808354040283529160200191610c16565b820191906000526020600020905b815481529060010190602001808311610bf957829003601f168201915b505050505081565b6000610c2b3384846106d5565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a72305820ea7b3a90a89969eb00d2a56f58b0f80481944475908acf25438759b53be73e5b0029",
					},
				},
				"12121856": map[string]interface{}{
					"360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9": map[string]interface{}{
						"balance": "0x0",
						"code":    "0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b9578063095ea7b31461014957806318160ddd146101ae57806323b872dd146101d95780632e1a7d4d1461025e578063313ce5671461028b57806370a08231146102bc57806395d89b4114610313578063a9059cbb146103a3578063d0e30db014610408578063dd62ed3e14610412575b6100b7610489565b005b3480156100c557600080fd5b506100ce610526565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010e5780820151818401526020810190506100f3565b50505050905090810190601f16801561013b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015557600080fd5b50610194600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610563565b604051808215151515815260200191505060405180910390f35b3480156101ba57600080fd5b506101c3610655565b6040518082815260200191505060405180910390f35b3480156101e557600080fd5b50610244600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610674565b604051808215151515815260200191505060405180910390f35b34801561026a57600080fd5b50610289600480360381019080803590602001909291905050506109c1565b005b34801561029757600080fd5b506102a0610af4565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102c857600080fd5b506102fd600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610afd565b6040518082815260200191505060405180910390f35b34801561031f57600080fd5b50610328610b15565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036857808201518184015260208101905061034d565b50505050905090810190601f1680156103955780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103af57600080fd5b506103ee600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b52565b604051808215151515815260200191505060405180910390f35b610410610489565b005b34801561041e57600080fd5b50610473600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b67565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60606040805190810160405280601f81526020017f5772617070656420506f6c79676f6e2045636f73797374656d20546f6b656e00815250905090565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156106c457600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415801561079c57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156108b75781600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561082c57600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a0f57600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610aa2573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b60006012905090565b60036020528060005260406000206000915090505481565b60606040805190810160405280600481526020017f57504f4c00000000000000000000000000000000000000000000000000000000815250905090565b6000610b5f338484610674565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058208d70d8aa2d752533105b5ccda8206dae8b0c1de765f89fb1f0c5727cbac1b40d0029",
					},
				},
			},
		},
	}

	BorMainnetChainConfig = &ChainConfig{
		ChainID:             big.NewInt(137),
		HomesteadBlock:      big.NewInt(0),
		DAOForkBlock:        nil,
		DAOForkSupport:      true,
		EIP150Block:         big.NewInt(0),
		EIP155Block:         big.NewInt(0),
		EIP158Block:         big.NewInt(0),
		ByzantiumBlock:      big.NewInt(0),
		ConstantinopleBlock: big.NewInt(0),
		PetersburgBlock:     big.NewInt(0),
		IstanbulBlock:       big.NewInt(3395000),
		MuirGlacierBlock:    big.NewInt(3395000),
		BerlinBlock:         big.NewInt(14750000),
		LondonBlock:         big.NewInt(23850000),
		ShanghaiBlock:       big.NewInt(50523000),
		CancunBlock:         big.NewInt(54876000),
		PragueBlock:         big.NewInt(73440256),
		Bor: &BorConfig{
			JaipurBlock:    big.NewInt(23850000),
			DelhiBlock:     big.NewInt(38189056),
			IndoreBlock:    big.NewInt(44934656),
			AhmedabadBlock: big.NewInt(62278656),
			BhilaiBlock:    big.NewInt(73440256),
			RioBlock:       big.NewInt(77414656),
			StateSyncConfirmationDelay: map[string]uint64{
				"44934656": 128,
			},

			Period: map[string]uint64{
				"0": 2,
			},
			ProducerDelay: map[string]uint64{
				"0":        6,
				"38189056": 4,
			},
			Sprint: map[string]uint64{
				"0":        64,
				"38189056": 16,
			},
			BackupMultiplier: map[string]uint64{
				"0": 2,
			},
			ValidatorContract:     "0x0000000000000000000000000000000000001000",
			StateReceiverContract: "0x0000000000000000000000000000000000001001",
			OverrideStateSyncRecords: map[string]int{
				"14949120": 8,
				"14949184": 0,
				"14953472": 0,
				"14953536": 5,
				"14953600": 0,
				"14953664": 0,
				"14953728": 0,
				"14953792": 0,
				"14953856": 0,
			},
			OverrideStateSyncRecordsInRange: []BlockRangeOverride{
				{StartBlock: 73812433, EndBlock: 73826700, Value: 0},
			},

			BurntContract: map[string]string{
				"23850000": "0x70bca57f4579f58670ab2d18ef16e02c17553c38",
				"50523000": "0x7A8ed27F4C30512326878652d20fC85727401854",
			},
			Coinbase: map[string]string{
				"0":        "0x0000000000000000000000000000000000000000",
				"77414656": "0x7Ee41D8A25641000661B1EF5E6AE8A00400466B0",
			},
			BlockAlloc: map[string]interface{}{
				// write as interface since that is how it is decoded in genesis
				"22156660": map[string]interface{}{
					"0000000000000000000000000000000000001010": map[string]interface{}{
						"balance": "0x0",
						"code":    "0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610caa565b005b3480156103eb57600080fd5b506103f4610dfc565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e05565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fc1565b005b3480156104e857600080fd5b506104f1611090565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b506105486110b6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110dc565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b506106046110fd565b005b34801561061257600080fd5b5061061b6111cd565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506111d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b50610758611358565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af611381565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de6113d8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e611411565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061144e565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b50610964611474565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b8101908080359060200190929190505050611501565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050611521565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a65611541565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a90611546565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb61154c565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115d9565b005b348015610b2e57600080fd5b50610b376115f6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b60006040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b60003390506000610cba826110dc565b9050610cd18360065461161c90919063ffffffff16565b600681905550600083118015610ce657508234145b610d58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610dd4876110dc565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610e0d611381565b610e1657600080fd5b600081118015610e535750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b610ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611da76023913960400191505060405180910390fd5b6000610eb3836110dc565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015610f00573d6000803e3d6000fd5b50610f168360065461163c90919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f68585610f98896110dc565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611027576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611d846023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061108c8261165b565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b611105611381565b61110e57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b60008060008060418551146111ee5760009350505050611352565b602085015192506040850151915060ff6041860151169050601b8160ff16101561121957601b810190505b601b8160ff16141580156112315750601c8160ff1614155b156112425760009350505050611352565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561129f573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561134e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600181526020017f890000000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b6000813414611460576000905061146e565b61146b338484611753565b90505b92915050565b6040518060800160405280605b8152602001611e1c605b91396040516020018082805190602001908083835b602083106114c357805182526020820191506020810190506020830392506114a0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061153761153286868686611b10565b611be6565b9050949350505050565b608981565b60015481565b604051806080016040528060528152602001611dca605291396040516020018082805190602001908083835b6020831061159b5780518252602082019150602081019050602083039250611578565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b6115e1611381565b6115ea57600080fd5b6115f38161165b565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282111561162b57600080fd5b600082840390508091505092915050565b60008082840190508381101561165157600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561169557600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117d357600080fd5b505afa1580156117e7573d6000803e3d6000fd5b505050506040513d60208110156117fd57600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561188f57600080fd5b505afa1580156118a3573d6000803e3d6000fd5b505050506040513d60208110156118b957600080fd5b810190808051906020019092919050505090506118d7868686611c30565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156119df57600080fd5b505afa1580156119f3573d6000803e3d6000fd5b505050506040513d6020811015611a0957600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a9757600080fd5b505afa158015611aab573d6000803e3d6000fd5b505050506040513d6020811015611ac157600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b6000806040518060800160405280605b8152602001611e1c605b91396040516020018082805190602001908083835b60208310611b625780518252602082019150602081019050602083039250611b3f565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611cd2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f63616e27742073656e6420746f204d524332300000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611d18573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a72315820a4a6f71a98ac3fc613c3a8f1e2e11b9eb9b6b39f125f7d9508916c2b8fb02c7164736f6c63430005100032",
					},
				},
				"50523000": map[string]interface{}{
					"0x0000000000000000000000000000000000001001": map[string]interface{}{
						"balance": "0x0",
						"code":    "0x608060405234801561001057600080fd5b506004361061005e576000357c01000000000000000000000000000000000000000000000000000000009004806319494a17146100635780633434735f146100fe5780635407ca6714610148575b600080fd5b6100e46004803603604081101561007957600080fd5b8101908080359060200190929190803590602001906401000000008111156100a057600080fd5b8201836020820111156100b257600080fd5b803590602001918460018302840111640100000000831117156100d457600080fd5b9091929391929390505050610166565b604051808215151515815260200191505060405180910390f35b6101066104d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101506104eb565b6040518082815260200191505060405180910390f35b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461021d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f742053797374656d2041646465737321000000000000000000000000000081525060200191505060405180910390fd5b606061027461026f85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506104f1565b61051f565b905060006102958260008151811061028857fe5b60200260200101516105fc565b90508060016000540114610311576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f537461746549647320617265206e6f742073657175656e7469616c000000000081525060200191505060405180910390fd5b600080815480929190600101919050555060006103418360018151811061033457fe5b602002602001015161066d565b905060606103628460028151811061035557fe5b6020026020010151610690565b905061036d8261071c565b156104c8576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103c75780820151818401526020810190506103ac565b50505050905090810190601f1680156103f45780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040527f26c53bea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008082516020840160008887f19650847f5a22725590b0a51c923940223f7458512164b1113359a735e86e7f27f44791ee88604051808215151515815260200191505060405180910390a250505b505050509392505050565b73fffffffffffffffffffffffffffffffffffffffe81565b60005481565b6104f961099c565b600060208301905060405180604001604052808451815260200182815250915050919050565b606061052a82610735565b61053357600080fd5b600061053e83610783565b905060608160405190808252806020026020018201604052801561057c57816020015b6105696109b6565b8152602001906001900390816105615790505b509050600061058e85602001516107f4565b8560200151019050600080600090505b848110156105ef576105af8361087d565b91506040518060400160405280838152602001848152508482815181106105d257fe5b60200260200101819052508183019250808060010191505061059e565b5082945050505050919050565b600080826000015111801561061657506021826000015111155b61061f57600080fd5b600061062e83602001516107f4565b9050600081846000015103905060008083866020015101905080519150602083101561066157826020036101000a820491505b81945050505050919050565b6000601582600001511461068057600080fd5b610689826105fc565b9050919050565b606060008260000151116106a357600080fd5b60006106b283602001516107f4565b905060008184600001510390506060816040519080825280601f01601f1916602001820160405280156106f45781602001600182028038833980820191505090505b5090506000816020019050610710848760200151018285610935565b81945050505050919050565b600080823b905060008163ffffffff1611915050919050565b6000808260000151141561074c576000905061077e565b60008083602001519050805160001a915060c060ff168260ff1610156107775760009250505061077e565b6001925050505b919050565b6000808260000151141561079a57600090506107ef565b600080905060006107ae84602001516107f4565b84602001510190506000846000015185602001510190505b808210156107e8576107d78261087d565b8201915082806001019350506107c6565b8293505050505b919050565b600080825160001a9050608060ff16811015610814576000915050610878565b60b860ff16811080610839575060c060ff168110158015610838575060f860ff1681105b5b15610848576001915050610878565b60c060ff168110156108685760018060b80360ff16820301915050610878565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561089e576001915061092b565b60b860ff168110156108bb576001608060ff16820301915061092a565b60c060ff168110156108eb5760b78103600185019450806020036101000a85510460018201810193505050610929565b60f860ff1681101561090857600160c060ff168203019150610928565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b600081141561094357610997565b5b602060ff1681106109735782518252602060ff1683019250602060ff1682019150602060ff1681039050610944565b6000600182602060ff16036101000a03905080198451168184511681811785525050505b505050565b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200160008152509056fea265627a7a723158208f1ea6fcf63d6911ac5dbfe340be1029614581802c6a750e7d6354b32ce6647c64736f6c63430005110032",
					},
				},
				"62278656": map[string]interface{}{
					// StateReceiver contract
					"0000000000000000000000000000000000001001": map[string]interface{}{
						"balance": "0x0",
						"code":    "0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635407ca671161008c578063abca220411610066578063abca2204146102fa578063d72a0b6714610302578063ee3a87f21461031f578063f165053614610342576100cf565b80635407ca67146102585780636757e5d914610260578063942af179146102f2576100cf565b806303112a17146100d457806319494a17146100f357806330e69fc31461017e578063318926f7146101985780633434735f146101bc57806351950cd9146101c4575b600080fd5b6100f1600480360360208110156100ea57600080fd5b503561034a565b005b61016a6004803603604081101561010957600080fd5b8135919081019060408101602082013564010000000081111561012b57600080fd5b82018360208201111561013d57600080fd5b8035906020019184600183028401116401000000008311171561015f57600080fd5b50909250905061060d565b604080519115158252519081900360200190f35b61018661093e565b60408051918252519081900360200190f35b6101a0610944565b604080516001600160a01b039092168252519081900360200190f35b6101a0610968565b6100f160048036036102808110156101db57600080fd5b61020082013590610220830135906001600160a01b036102408501351690840184610280810161026082013564010000000081111561021957600080fd5b82018360208201111561022b57600080fd5b8035906020019184600183028401116401000000008311171561024d57600080fd5b509092509050610973565b610186610c78565b61027d6004803603602081101561027657600080fd5b5035610c7e565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102b757818101518382015260200161029f565b50505050905090810190601f1680156102e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610186610d19565b610186610d1f565b61016a6004803603602081101561031857600080fd5b5035610d25565b6100f16004803603604081101561033557600080fd5b5080359060200135610d3a565b610186610db0565b60008181526003602090815260409182902080548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452606093928301828280156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b50505050509050805160001415610426576040805162461bcd60e51b815260206004820152600660248201526508599bdd5b9960d21b604482015290519081900360640190fd5b600082815260036020526040812061043d916112bb565b6000606082806020019051604081101561045657600080fd5b81516020830180516040519294929383019291908464010000000082111561047d57600080fd5b90830190602082018581111561049257600080fd5b82516401000000008111828201881017156104ac57600080fd5b82525081516020918201929091019080838360005b838110156104d95781810151838201526020016104c1565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b5060405250505091509150837f8797144948782adcede8e04bfa0bd8fd56941e0df7508bd02a629b477f7b073a60405160405180910390a2604080516313629df560e11b815260048101868152602482019283528351604483015283516001600160a01b038616936326c53bea938993879390929160640190602085019080838360005b838110156105a257818101518382015260200161058a565b50505050905090810190601f1680156105cf5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156105ef57600080fd5b505af1158015610603573d6000803e3d6000fd5b5050505050505050565b6000336002600160a01b031461065f576040805162461bcd60e51b81526020600482015260126024820152714e6f742053797374656d204164646573732160701b604482015290519081900360640190fd5b60606106a86106a385858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610db592505050565b610ddb565b905060006106c9826000815181106106bc57fe5b6020026020010151610f14565b90508060005460010114610724576040805162461bcd60e51b815260206004820152601b60248201527f537461746549647320617265206e6f742073657175656e7469616c0000000000604482015290519081900360640190fd5b6000805460019081018255835161074c918591811061073f57fe5b6020026020010151610f62565b9050606061076d8460028151811061076057fe5b6020026020010151610f82565b905061077882610fff565b15610933576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107cf5781810151838201526020016107b7565b50505050905090810190601f1680156107fc5780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529190526020810180516001600160e01b03166313629df560e11b1781528151919650600095508594509092509050828887f1604080518215158152905191985086917f5a22725590b0a51c923940223f7458512164b1113359a735e86e7f27f44791ee9181900360200190a28661093057838360405160200180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108cc5781810151838201526020016108b4565b50505050905090810190601f1680156108f95780820380516001836020036101000a031916815260200191505b5060408051601f1981840301815291815260008b815260036020908152919020825161092e9750909550910192509050611302565b505b50505b505050509392505050565b60045481565b7f000000000000000000000000eb1cd9e44ab6bfe5a55ee96c468086e51b1b873a81565b6002600160a01b0381565b6201000085106109be576040805162461bcd60e51b81526020600482015260116024820152700d2dcecc2d8d2c840d8cac2cc92dcc8caf607b1b604482015290519081900360640190fd5b60045460058054600101908190551115610a05576040805162461bcd60e51b8152602060048201526003602482015262195b9960ea1b604482015290519081900360640190fd5b60015480610a42576040805162461bcd60e51b8152602060048201526005602482015264085c9bdbdd60da1b604482015290519081900360640190fd5b60008585858560405160200180858152602001846001600160a01b0316815260200180602001828103825284848281815260200192508082843760008184015260408051601f19601f909301831690940184810390920184525250805160209091012096507f28cf91ac064e179f8a42e4b7a20ba080187781da55fd4f3f18870b7a25bacb559550505050828414801592509050610aef575060008281526002602052604090205460ff16155b610b29576040805162461bcd60e51b815260206004808301919091526024820152631d5cd95960e21b604482015290519081900360640190fd5b60008281526002602052604090819020805460ff191660011790558051610200818101909252610b74918b9060109083908390808284376000920191909152508b915085905061100b565b8314610bb0576040805162461bcd60e51b815260206004820152600660248201526510b83937b7b360d11b604482015290519081900360640190fd5b60405187907f8797144948782adcede8e04bfa0bd8fd56941e0df7508bd02a629b477f7b073a90600090a2604080516313629df560e11b81526004810189815260248201928352604482018790526001600160a01b038916926326c53bea928b928a928a92606401848480828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b158015610c5557600080fd5b505af1158015610c69573d6000803e3d6000fd5b50505050505050505050505050565b60005481565b60036020908152600091825260409182902080548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084529091830182828015610d115780601f10610ce657610100808354040283529160200191610d11565b820191906000526020600020905b815481529060010190602001808311610cf457829003601f168201915b505050505081565b60055481565b60015481565b60026020526000908152604090205460ff1681565b336001600160a01b037f000000000000000000000000eb1cd9e44ab6bfe5a55ee96c468086e51b1b873a1614610da5576040805162461bcd60e51b815260206004820152600b60248201526a10b937b7ba29b2ba3a32b960a91b604482015290519081900360640190fd5b600191909155600455565b601081565b610dbd611380565b5060408051808201909152815181526020828101908201525b919050565b6060610de6826110b6565b610def57600080fd5b6000610dfa836110f0565b905060608167ffffffffffffffff81118015610e1557600080fd5b50604051908082528060200260200182016040528015610e4f57816020015b610e3c611380565b815260200190600190039081610e345790505b5090506000610e618560200151611148565b60208601510190506000805b84811015610eb857610e7e836111ab565b9150604051806040016040528083815260200184815250848281518110610ea157fe5b602090810291909101015291810191600101610e6d565b5085516020870151830314610f0a576040805162461bcd60e51b81526020600482015260136024820152722bb937b733903a37ba30b6103632b733ba341760691b604482015290519081900360640190fd5b5090949350505050565b805160009015801590610f2957508151602110155b610f3257600080fd5b600080610f3e84611244565b815191935091506020821015610f5a5760208290036101000a90045b949350505050565b8051600090601514610f7357600080fd5b610f7c82610f14565b92915050565b8051606090610f9057600080fd5b600080610f9c84611244565b9150915060608167ffffffffffffffff81118015610fb957600080fd5b506040519080825280601f01601f191660200182016040528015610fe4576020820181803683370190505b50905060208101610ff684828561126a565b50949350505050565b3b63ffffffff16151590565b600081815b6010811015610ff657600185821c8116141561106c5785816010811061103257fe5b60200201518260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091506110ae565b8186826010811061107957fe5b602002015160405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091505b600101611010565b80516000906110c757506000610dd6565b6020820151805160001a9060c08210156110e657600092505050610dd6565b5060019392505050565b805160009061110157506000610dd6565b6000806111118460200151611148565b602085015185519181019250015b8082101561113f57611130826111ab565b6001909301929091019061111f565b50909392505050565b8051600090811a6080811015611162576000915050610dd6565b60b881108061117d575060c0811080159061117d575060f881105b1561118c576001915050610dd6565b60c08110156111a05760b519019050610dd6565b60f519019050610dd6565b80516000908190811a60808110156111c6576001915061123d565b60b88110156111db57607e198101915061123d565b60c08110156112085760b78103600185019450806020036101000a8551046001820181019350505061123d565b60f881101561121d5760be198101915061123d565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60008060006112568460200151611148565b602085015194519481019594039392505050565b80611274576112b6565b5b60208110611294578251825260209283019290910190601f1901611275565b80156112b6578251825160208390036101000a60001901801990921691161782525b505050565b50805460018160011615610100020316600290046000825580601f106112e157506112ff565b601f0160209004906000526020600020908101906112ff919061139a565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061134357805160ff1916838001178555611370565b82800160010185558215611370579182015b82811115611370578251825591602001919060010190611355565b5061137c92915061139a565b5090565b604051806040016040528060008152602001600081525090565b5b8082111561137c576000815560010161139b56fea164736f6c634300060c000a",
					},
					// MRC20 contract
					"0000000000000000000000000000000000001010": map[string]interface{}{
						"balance": "0x0",
						"code":    "0x6080604052600436106101b75760003560e01c80638da5cb5b116100ec578063b789543c1161008a578063e614d0d611610064578063e614d0d614610695578063ed9ef524146106aa578063f2fde38b146106dd578063fc0c546a14610710576101b7565b8063b789543c14610626578063cc79f97b1461066b578063e306f77914610680576101b7565b806395d89b41116100c657806395d89b41146105a6578063a9059cbb146105bb578063abceeba2146105e7578063acd06cb3146105fc576101b7565b80638da5cb5b146105535780638f32d59b146105685780639025e64c14610591576101b7565b806347e7ef241161015957806370a082311161013357806370a082311461043c578063715018a61461046f578063771282f61461048457806377d32e9414610499576101b7565b806347e7ef24146103b3578063485cc955146103ec57806360f96a8f14610427576101b7565b806319d27d9c1161019557806319d27d9c146102a25780632e1a7d4d14610356578063313ce5671461037357806342fc47fb1461039e576101b7565b806306fdde03146101bc5780631499c5921461024657806318160ddd1461027b575b600080fd5b3480156101c857600080fd5b506101d1610725565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561020b5781810151838201526020016101f3565b50505050905090810190601f1680156102385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025257600080fd5b506102796004803603602081101561026957600080fd5b50356001600160a01b031661075c565b005b34801561028757600080fd5b5061029061079c565b60408051918252519081900360200190f35b3480156102ae57600080fd5b5061033a600480360360a08110156102c557600080fd5b8101906020810181356401000000008111156102e057600080fd5b8201836020820111156102f257600080fd5b8035906020019184600183028401116401000000008311171561031457600080fd5b9193509150803590602081013590604081013590606001356001600160a01b03166107ac565b604080516001600160a01b039092168252519081900360200190f35b6102796004803603602081101561036c57600080fd5b50356107ee565b34801561037f57600080fd5b506103886108c6565b6040805160ff9092168252519081900360200190f35b3480156103aa57600080fd5b5061033a6108cb565b3480156103bf57600080fd5b50610279600480360360408110156103d657600080fd5b506001600160a01b0381351690602001356108da565b3480156103f857600080fd5b506102796004803603604081101561040f57600080fd5b506001600160a01b03813581169160200135166109a8565b34801561043357600080fd5b5061033a610a21565b34801561044857600080fd5b506102906004803603602081101561045f57600080fd5b50356001600160a01b0316610a30565b34801561047b57600080fd5b50610279610a3d565b34801561049057600080fd5b50610290610a98565b3480156104a557600080fd5b5061033a600480360360408110156104bc57600080fd5b813591908101906040810160208201356401000000008111156104de57600080fd5b8201836020820111156104f057600080fd5b8035906020019184600183028401116401000000008311171561051257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610a9e945050505050565b34801561055f57600080fd5b5061033a610bc2565b34801561057457600080fd5b5061057d610bd1565b604080519115158252519081900360200190f35b34801561059d57600080fd5b506101d1610be2565b3480156105b257600080fd5b506101d1610c00565b61057d600480360360408110156105d157600080fd5b506001600160a01b038135169060200135610c1d565b3480156105f357600080fd5b50610290610c40565b34801561060857600080fd5b5061057d6004803603602081101561061f57600080fd5b5035610cc9565b34801561063257600080fd5b506102906004803603608081101561064957600080fd5b506001600160a01b038135169060208101359060408101359060600135610cde565b34801561067757600080fd5b50610290610cfd565b34801561068c57600080fd5b50610290610d03565b3480156106a157600080fd5b50610290610d09565b3480156106b657600080fd5b50610279600480360360208110156106cd57600080fd5b50356001600160a01b0316610d53565b3480156106e957600080fd5b506102796004803603602081101561070057600080fd5b50356001600160a01b0316610e05565b34801561071c57600080fd5b5061033a610e22565b60408051808201909152601781527f506f6c79676f6e2045636f73797374656d20546f6b656e000000000000000000602082015290565b6040805162461bcd60e51b815260206004820152601060248201526f44697361626c6564206665617475726560801b604482015290519081900360640190fd5b6b204fce5e3e2502611000000090565b6040805162461bcd60e51b815260206004820152601060248201526f44697361626c6564206665617475726560801b6044820152905160009181900360640190fd5b3360006107fa82610a30565b600654909150610810908463ffffffff610e3116565b600655821580159061082157508234145b610868576040805162461bcd60e51b8152602060048201526013602482015272125b9cdd59999a58da595b9d08185b5bdd5b9d606a1b604482015290519081900360640190fd5b6002546001600160a01b0380841691167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f85846108a487610a30565b60408051938452602084019290925282820152519081900360600190a3505050565b601290565b6003546001600160a01b031681565b6108e2610bd1565b6108eb57600080fd5b60008111801561090357506001600160a01b03821615155b61093e5760405162461bcd60e51b815260040180806020018281038252602381526020018061138d6023913960400191505060405180910390fd5b600061094983610a30565b60065490915061095f908363ffffffff610e4616565b60065561096c8383610e58565b6002546001600160a01b0380851691167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f684846108a488610a30565b60075460ff16156109ea5760405162461bcd60e51b815260040180806020018281038252602381526020018061136a6023913960400191505060405180910390fd5b6007805460ff19166001179055600280546001600160a01b0383166001600160a01b0319909116179055610a1d82610f17565b5050565b6004546001600160a01b031681565b6001600160a01b03163190565b610a45610bd1565b610a4e57600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60065481565b6000806000808451604114610ab95760009350505050610bbc565b50505060208201516040830151604184015160ff16601b811015610adb57601b015b8060ff16601b14158015610af357508060ff16601c14155b15610b045760009350505050610bbc565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa158015610b5b573d6000803e3d6000fd5b5050604051601f1901519450506001600160a01b038416610bb8576040805162461bcd60e51b815260206004820152601260248201527122b93937b91034b71032b1b932b1b7bb32b960711b604482015290519081900360640190fd5b5050505b92915050565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b604051806040016040528060028152602001613a9960f01b81525081565b6040805180820190915260038152621413d360ea1b602082015290565b6000813414610c2e57506000610bbc565b610c39338484610f85565b9392505050565b6040518060800160405280605b8152602001611434605b91396040516020018082805190602001908083835b60208310610c8b5780518252601f199092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020526000908152604090205460ff1681565b6000610cf4610cef868686866111d2565b61128b565b95945050505050565b613a9981565b60015481565b6040518060800160405280605281526020016113b06052913960405160200180828051906020019080838360208310610c8b5780518252601f199092019160209182019101610c6c565b610d5b610bd1565b610d6457600080fd5b6001600160a01b038116610da95760405162461bcd60e51b81526004018080602001828103825260328152602001806114026032913960400191505060405180910390fd5b6003546040516001600160a01b038084169216907f1f9f3556dd336016cdf20adaead7d5c73665dba664b60e8c17e9a4eb91ce1d3990600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b610e0d610bd1565b610e1657600080fd5b610e1f81610f17565b50565b6002546001600160a01b031681565b600082821115610e4057600080fd5b50900390565b600082820183811015610c3957600080fd5b60085415610e9a576040805162461bcd60e51b815260206004820152600a6024820152697265656e7472616e637960b01b604482015290519081900360640190fd5b6001600855604051611388906000906060906001600160a01b038616908490869085818181858888f193505050503d8060008114610ef4576040519150601f19603f3d011682016040523d82523d6000602084013e610ef9565b606091505b509150915081610f0b57805160208201fd5b50506000600855505050565b6001600160a01b038116610f2a57600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516370a0823160e01b81526001600160a01b03851660048201529051600091829130916370a08231916024808301926020929190829003018186803b158015610fd057600080fd5b505afa158015610fe4573d6000803e3d6000fd5b505050506040513d6020811015610ffa57600080fd5b5051604080516370a0823160e01b81526001600160a01b0387166004820152905191925060009130916370a08231916024808301926020929190829003018186803b15801561104857600080fd5b505afa15801561105c573d6000803e3d6000fd5b505050506040513d602081101561107257600080fd5b50519050611081868686611299565b600254604080516370a0823160e01b81526001600160a01b03898116600483018190529251818a1694909116917fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c49189918891889130916370a0823191602480820192602092909190829003018186803b1580156110fe57600080fd5b505afa158015611112573d6000803e3d6000fd5b505050506040513d602081101561112857600080fd5b5051604080516370a0823160e01b81526001600160a01b038f166004820152905130916370a08231916024808301926020929190829003018186803b15801561117057600080fd5b505afa158015611184573d6000803e3d6000fd5b505050506040513d602081101561119a57600080fd5b50516040805195865260208601949094528484019290925260608401526080830152519081900360a00190a450600195945050505050565b6000806040518060800160405280605b8152602001611434605b91396040516020018082805190602001908083835b602083106112205780518252601f199092019160209182019101611201565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835280855282519282019290922082526001600160a01b039b909b169a81019a909a5250880196909652505050606084019190915260808301525060a0902090565b6000610bbc82600154611347565b6001600160a01b0382163014156112ed576040805162461bcd60e51b8152602060048201526013602482015272063616e27742073656e6420746f204d5243323606c1b604482015290519081900360640190fd5b6112f78282610e58565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b60405161190160f01b815260028101919091526022810191909152604290209056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e7472616374294368696c6420746f6b656e3a206e6577206368696c64206164647265737320697320746865207a65726f2061646472657373546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a723158205f23be7574e70cfc01d0cfd6803b871f92465e9ae4a10fe95ed31ccb810bda3e64736f6c63430005110032",
					},
					// WMATIC contract
					"0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270": map[string]interface{}{
						"balance": "0x0",
						"code":    "0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b9578063095ea7b31461014957806318160ddd146101ae57806323b872dd146101d95780632e1a7d4d1461025e578063313ce5671461028b57806370a08231146102bc57806395d89b4114610313578063a9059cbb146103a3578063d0e30db014610408578063dd62ed3e14610412575b6100b7610489565b005b3480156100c557600080fd5b506100ce610526565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010e5780820151818401526020810190506100f3565b50505050905090810190601f16801561013b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015557600080fd5b50610194600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610563565b604051808215151515815260200191505060405180910390f35b3480156101ba57600080fd5b506101c3610655565b6040518082815260200191505060405180910390f35b3480156101e557600080fd5b50610244600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610674565b604051808215151515815260200191505060405180910390f35b34801561026a57600080fd5b50610289600480360381019080803590602001909291905050506109c1565b005b34801561029757600080fd5b506102a0610af4565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102c857600080fd5b506102fd600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610afd565b6040518082815260200191505060405180910390f35b34801561031f57600080fd5b50610328610b15565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036857808201518184015260208101905061034d565b50505050905090810190601f1680156103955780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103af57600080fd5b506103ee600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b52565b604051808215151515815260200191505060405180910390f35b610410610489565b005b34801561041e57600080fd5b50610473600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b67565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60606040805190810160405280601f81526020017f5772617070656420506f6c79676f6e2045636f73797374656d20546f6b656e00815250905090565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156106c457600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415801561079c57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156108b75781600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561082c57600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a0f57600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610aa2573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b60006012905090565b60036020528060005260406000206000915090505481565b60606040805190810160405280600481526020017f57504f4c00000000000000000000000000000000000000000000000000000000815250905090565b6000610b5f338484610674565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058208d70d8aa2d752533105b5ccda8206dae8b0c1de765f89fb1f0c5727cbac1b40d0029",
					},
				},
			},
		},
	}

	// AllEthashProtocolChanges contains every protocol change (EIPs) introduced
	// and accepted by the Ethereum core developers into the Ethash consensus.
	AllEthashProtocolChanges = &ChainConfig{
		ChainID:                 big.NewInt(1337),
		HomesteadBlock:          big.NewInt(0),
		DAOForkBlock:            nil,
		DAOForkSupport:          false,
		EIP150Block:             big.NewInt(0),
		EIP155Block:             big.NewInt(0),
		EIP158Block:             big.NewInt(0),
		ByzantiumBlock:          big.NewInt(0),
		ConstantinopleBlock:     big.NewInt(0),
		PetersburgBlock:         big.NewInt(0),
		IstanbulBlock:           big.NewInt(0),
		MuirGlacierBlock:        big.NewInt(0),
		BerlinBlock:             big.NewInt(0),
		LondonBlock:             big.NewInt(0),
		ArrowGlacierBlock:       big.NewInt(0),
		GrayGlacierBlock:        big.NewInt(0),
		TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
		MergeNetsplitBlock:      nil,
		ShanghaiBlock:           nil,
		CancunBlock:             nil,
		PragueBlock:             nil,
		OsakaBlock:              nil,
		VerkleBlock:             nil,
		Ethash:                  new(EthashConfig),
		Clique:                  nil,
		Bor: &BorConfig{
			BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"},
			Period:        map[string]uint64{"0": 2},
		},
	}

	AllDevChainProtocolChanges = &ChainConfig{
		ChainID:                 big.NewInt(1337),
		HomesteadBlock:          big.NewInt(0),
		EIP150Block:             big.NewInt(0),
		EIP155Block:             big.NewInt(0),
		EIP158Block:             big.NewInt(0),
		ByzantiumBlock:          big.NewInt(0),
		ConstantinopleBlock:     big.NewInt(0),
		PetersburgBlock:         big.NewInt(0),
		IstanbulBlock:           big.NewInt(0),
		MuirGlacierBlock:        big.NewInt(0),
		BerlinBlock:             big.NewInt(0),
		LondonBlock:             big.NewInt(0),
		ArrowGlacierBlock:       big.NewInt(0),
		GrayGlacierBlock:        big.NewInt(0),
		ShanghaiBlock:           big.NewInt(0),
		CancunBlock:             big.NewInt(0),
		TerminalTotalDifficulty: big.NewInt(0),
		PragueBlock:             big.NewInt(0),
		BlobScheduleConfig: &BlobScheduleConfig{
			Cancun: DefaultCancunBlobConfig,
			Prague: DefaultPragueBlobConfig,
		},
		Bor: &BorConfig{
			BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"},
			Period:        map[string]uint64{"0": 2},
		},
	}

	AllDevChainProtocolChanges1 = &ChainConfig{
		ChainID:                 big.NewInt(1337),
		HomesteadBlock:          big.NewInt(0),
		EIP150Block:             big.NewInt(0),
		EIP155Block:             big.NewInt(0),
		EIP158Block:             big.NewInt(0),
		ByzantiumBlock:          big.NewInt(0),
		ConstantinopleBlock:     big.NewInt(0),
		PetersburgBlock:         big.NewInt(0),
		IstanbulBlock:           big.NewInt(0),
		MuirGlacierBlock:        big.NewInt(0),
		BerlinBlock:             big.NewInt(0),
		LondonBlock:             big.NewInt(0),
		ArrowGlacierBlock:       big.NewInt(0),
		GrayGlacierBlock:        big.NewInt(0),
		TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
		BlobScheduleConfig: &BlobScheduleConfig{
			Cancun: DefaultCancunBlobConfig,
			Prague: DefaultPragueBlobConfig,
		},
		Bor: &BorConfig{
			BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"},
			Period:        map[string]uint64{"0": 2},
		},
	}

	// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
	// and accepted by the Ethereum core developers into the Clique consensus.
	AllCliqueProtocolChanges = &ChainConfig{
		ChainID:                 big.NewInt(1337),
		HomesteadBlock:          big.NewInt(0),
		DAOForkBlock:            nil,
		DAOForkSupport:          false,
		EIP150Block:             big.NewInt(0),
		EIP155Block:             big.NewInt(0),
		EIP158Block:             big.NewInt(0),
		ByzantiumBlock:          big.NewInt(0),
		ConstantinopleBlock:     big.NewInt(0),
		PetersburgBlock:         big.NewInt(0),
		IstanbulBlock:           big.NewInt(0),
		MuirGlacierBlock:        big.NewInt(0),
		BerlinBlock:             big.NewInt(0),
		LondonBlock:             big.NewInt(0),
		ArrowGlacierBlock:       nil,
		GrayGlacierBlock:        nil,
		MergeNetsplitBlock:      nil,
		ShanghaiBlock:           nil,
		CancunBlock:             nil,
		PragueBlock:             nil,
		OsakaBlock:              nil,
		VerkleBlock:             nil,
		TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
		Ethash:                  nil,
		Clique:                  &CliqueConfig{Period: 0, Epoch: 30000},
		Bor: &BorConfig{
			BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"},
			Period:        map[string]uint64{"0": 2},
		},
	}

	// TestChainConfig contains every protocol change (EIPs) introduced
	// and accepted by the Ethereum core developers for testing purposes.
	TestChainConfig = &ChainConfig{
		ChainID:                 big.NewInt(1),
		HomesteadBlock:          big.NewInt(0),
		DAOForkBlock:            nil,
		DAOForkSupport:          false,
		EIP150Block:             big.NewInt(0),
		EIP155Block:             big.NewInt(0),
		EIP158Block:             big.NewInt(0),
		ByzantiumBlock:          big.NewInt(0),
		ConstantinopleBlock:     big.NewInt(0),
		PetersburgBlock:         big.NewInt(0),
		IstanbulBlock:           big.NewInt(0),
		MuirGlacierBlock:        big.NewInt(0),
		BerlinBlock:             big.NewInt(0),
		LondonBlock:             big.NewInt(0),
		ArrowGlacierBlock:       big.NewInt(0),
		GrayGlacierBlock:        big.NewInt(0),
		MergeNetsplitBlock:      nil,
		ShanghaiBlock:           nil,
		CancunBlock:             nil,
		PragueBlock:             nil,
		OsakaBlock:              nil,
		VerkleBlock:             nil,
		TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
		Ethash:                  new(EthashConfig),
		Clique:                  nil,
		BlobScheduleConfig: &BlobScheduleConfig{
			Cancun: DefaultCancunBlobConfig,
			Prague: DefaultPragueBlobConfig,
		},
		Bor: &BorConfig{
			Sprint: map[string]uint64{
				"0": 4},
			BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"},
			Period:        map[string]uint64{"0": 2},
		},
	}

	// MergedTestChainConfig contains every protocol change (EIPs) introduced
	// and accepted by the Ethereum core developers for testing purposes.
	MergedTestChainConfig = &ChainConfig{
		ChainID:                 big.NewInt(1),
		HomesteadBlock:          big.NewInt(0),
		DAOForkBlock:            nil,
		DAOForkSupport:          false,
		EIP150Block:             big.NewInt(0),
		EIP155Block:             big.NewInt(0),
		EIP158Block:             big.NewInt(0),
		ByzantiumBlock:          big.NewInt(0),
		ConstantinopleBlock:     big.NewInt(0),
		PetersburgBlock:         big.NewInt(0),
		IstanbulBlock:           big.NewInt(0),
		MuirGlacierBlock:        big.NewInt(0),
		BerlinBlock:             big.NewInt(0),
		LondonBlock:             big.NewInt(0),
		ArrowGlacierBlock:       big.NewInt(0),
		GrayGlacierBlock:        big.NewInt(0),
		MergeNetsplitBlock:      big.NewInt(0),
		ShanghaiBlock:           big.NewInt(0),
		CancunBlock:             big.NewInt(0),
		PragueBlock:             big.NewInt(0),
		OsakaBlock:              big.NewInt(0),
		VerkleBlock:             nil,
		TerminalTotalDifficulty: big.NewInt(0),
		Ethash:                  new(EthashConfig),
		Clique:                  nil,
		BlobScheduleConfig: &BlobScheduleConfig{
			Cancun: DefaultCancunBlobConfig,
			Prague: DefaultPragueBlobConfig,
		},
		Bor: &BorConfig{
			Sprint: map[string]uint64{
				"0": 4},
			BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"},
			Period:        map[string]uint64{"0": 2},
		},
	}

	// NonActivatedConfig defines the chain configuration without activating
	// any protocol change (EIPs).
	NonActivatedConfig = &ChainConfig{
		ChainID:                 big.NewInt(1),
		HomesteadBlock:          nil,
		DAOForkBlock:            nil,
		DAOForkSupport:          false,
		EIP150Block:             nil,
		EIP155Block:             nil,
		EIP158Block:             nil,
		ByzantiumBlock:          nil,
		ConstantinopleBlock:     nil,
		PetersburgBlock:         nil,
		IstanbulBlock:           nil,
		MuirGlacierBlock:        nil,
		BerlinBlock:             nil,
		LondonBlock:             nil,
		ArrowGlacierBlock:       nil,
		GrayGlacierBlock:        nil,
		MergeNetsplitBlock:      nil,
		ShanghaiBlock:           nil,
		CancunBlock:             nil,
		PragueBlock:             nil,
		VerkleBlock:             nil,
		OsakaBlock:              nil,
		TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
		Ethash:                  new(EthashConfig),
		Clique:                  nil,
	}
	TestRules = TestChainConfig.Rules(new(big.Int), false, 0)
)

var (
	// DefaultCancunBlobConfig is the default blob configuration for the Cancun fork.
	DefaultCancunBlobConfig = &BlobConfig{
		Target:         3,
		Max:            6,
		UpdateFraction: 3338477,
	}
	// DefaultPragueBlobConfig is the default blob configuration for the Prague fork.
	DefaultPragueBlobConfig = &BlobConfig{
		Target:         6,
		Max:            9,
		UpdateFraction: 5007716,
	}
	// DefaultOsakaBlobConfig is the default blob configuration for the Osaka fork.
	DefaultOsakaBlobConfig = &BlobConfig{
		Target:         6,
		Max:            9,
		UpdateFraction: 5007716,
	}
	// DefaultBlobSchedule is the latest configured blob schedule for Ethereum mainnet.
	DefaultBlobSchedule = &BlobScheduleConfig{
		Cancun: DefaultCancunBlobConfig,
		Prague: DefaultPragueBlobConfig,
		Osaka:  DefaultOsakaBlobConfig,
	}
)

// NetworkNames are user friendly names to use in the chain spec banner.
var NetworkNames = map[string]string{
	MainnetChainConfig.ChainID.String():    "mainnet",
	GoerliChainConfig.ChainID.String():     "goerli",
	SepoliaChainConfig.ChainID.String():    "sepolia",
	HoleskyChainConfig.ChainID.String():    "holesky",
	HoodiChainConfig.ChainID.String():      "hoodi",
	BorMainnetChainConfig.ChainID.String(): "bor",
	MumbaiChainConfig.ChainID.String():     "mumbai",
	AmoyChainConfig.ChainID.String():       "amoy",
}

// ChainConfig is the core config which determines the blockchain settings.
//
// ChainConfig is stored in the database on a per block basis. This means
// that any network, identified by its genesis block, can have its own
// set of configuration options.
type ChainConfig struct {
	ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection

	HomesteadBlock *big.Int `json:"homesteadBlock,omitempty"` // Homestead switch block (nil = no fork, 0 = already homestead)

	DAOForkBlock   *big.Int `json:"daoForkBlock,omitempty"`   // TheDAO hard-fork switch block (nil = no fork)
	DAOForkSupport bool     `json:"daoForkSupport,omitempty"` // Whether the nodes supports or opposes the DAO hard-fork

	// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
	EIP150Block *big.Int `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork)
	EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block
	EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block

	ByzantiumBlock      *big.Int `json:"byzantiumBlock,omitempty"`      // Byzantium switch block (nil = no fork, 0 = already on byzantium)
	ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated)
	PetersburgBlock     *big.Int `json:"petersburgBlock,omitempty"`     // Petersburg switch block (nil = same as Constantinople)
	IstanbulBlock       *big.Int `json:"istanbulBlock,omitempty"`       // Istanbul switch block (nil = no fork, 0 = already on istanbul)
	MuirGlacierBlock    *big.Int `json:"muirGlacierBlock,omitempty"`    // Eip-2384 (bomb delay) switch block (nil = no fork, 0 = already activated)
	BerlinBlock         *big.Int `json:"berlinBlock,omitempty"`         // Berlin switch block (nil = no fork, 0 = already on berlin)
	LondonBlock         *big.Int `json:"londonBlock,omitempty"`         // London switch block (nil = no fork, 0 = already on london)
	ArrowGlacierBlock   *big.Int `json:"arrowGlacierBlock,omitempty"`   // Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
	GrayGlacierBlock    *big.Int `json:"grayGlacierBlock,omitempty"`    // Eip-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
	MergeNetsplitBlock  *big.Int `json:"mergeNetsplitBlock,omitempty"`  // Virtual fork after The Merge to use as a network splitter

	// Fork scheduling was switched from blocks to timestamps here
	// Fork scheduling switched back to blockNumber in Bor
	ShanghaiBlock *big.Int `json:"shanghaiBlock,omitempty"` // Shanghai switch Block (nil = no fork, 0 = already on shanghai)
	CancunBlock   *big.Int `json:"cancunBlock,omitempty"`   // Cancun switch Block (nil = no fork, 0 = already on cancun)
	PragueBlock   *big.Int `json:"pragueBlock,omitempty"`   // Prague switch Block (nil = no fork, 0 = already on prague)
	VerkleBlock   *big.Int `json:"verkleBlock,omitempty"`   // Verkle switch Block (nil = no fork, 0 = already on verkle)
	OsakaBlock    *big.Int `json:"osakaBlock,omitempty"`    // Osaka switch Block (nil = no fork, 0 = already on osaka)

	// TerminalTotalDifficulty is the amount of total difficulty reached by
	// the network that triggers the consensus upgrade.
	TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"`

	DepositContractAddress common.Address `json:"depositContractAddress,omitempty"`

	// EnableVerkleAtGenesis is a flag that specifies whether the network uses
	// the Verkle tree starting from the genesis block. If set to true, the
	// genesis state will be committed using the Verkle tree, eliminating the
	// need for any Verkle transition later.
	//
	// This is a temporary flag only for verkle devnet testing, where verkle is
	// activated at genesis, and the configured activation date has already passed.
	//
	// In production networks (mainnet and public testnets), verkle activation
	// always occurs after the genesis block, making this flag irrelevant in
	// those cases.
	EnableVerkleAtGenesis bool `json:"enableVerkleAtGenesis,omitempty"`

	// Various consensus engines
	Bor                *BorConfig          `json:"bor,omitempty"`
	Ethash             *EthashConfig       `json:"ethash,omitempty"`
	Clique             *CliqueConfig       `json:"clique,omitempty"`
	BlobScheduleConfig *BlobScheduleConfig `json:"blobSchedule,omitempty"`
}

// EthashConfig is the consensus engine configs for proof-of-work based sealing.
type EthashConfig struct{}

// String implements the stringer interface, returning the consensus engine details.
func (c EthashConfig) String() string {
	return "ethash"
}

// CliqueConfig is the consensus engine configs for proof-of-authority based sealing.
type CliqueConfig struct {
	Period uint64 `json:"period"` // Number of seconds between blocks to enforce
	Epoch  uint64 `json:"epoch"`  // Epoch length to reset votes and checkpoint
}

// String implements the stringer interface, returning the consensus engine details.
func (c CliqueConfig) String() string {
	return fmt.Sprintf("clique(period: %d, epoch: %d)", c.Period, c.Epoch)
}

type BlockRangeOverride struct {
	StartBlock uint64 `json:"startBlock"`
	EndBlock   uint64 `json:"endBlock"`
	Value      int    `json:"value"`
}

// BorConfig is the consensus engine configs for Matic bor based sealing.
type BorConfig struct {
	Period                          map[string]uint64      `json:"period"`                          // Number of seconds between blocks to enforce
	ProducerDelay                   map[string]uint64      `json:"producerDelay"`                   // Number of seconds delay between two producer interval
	Sprint                          map[string]uint64      `json:"sprint"`                          // Epoch length to proposer
	BackupMultiplier                map[string]uint64      `json:"backupMultiplier"`                // Backup multiplier to determine the wiggle time
	ValidatorContract               string                 `json:"validatorContract"`               // Validator set contract
	StateReceiverContract           string                 `json:"stateReceiverContract"`           // State receiver contract
	OverrideStateSyncRecords        map[string]int         `json:"overrideStateSyncRecords"`        // override state records count
	OverrideStateSyncRecordsInRange []BlockRangeOverride   `json:"overrideStateSyncRecordsInRange"` // override state records count in a given block range
	BlockAlloc                      map[string]interface{} `json:"blockAlloc"`
	BurntContract                   map[string]string      `json:"burntContract"`              // governance contract where the token will be sent to and burnt in london fork
	Coinbase                        map[string]string      `json:"coinbase"`                   // coinbase address
	SkipValidatorByteCheck          []uint64               `json:"skipValidatorByteCheck"`     // skip validator byte check
	JaipurBlock                     *big.Int               `json:"jaipurBlock"`                // Jaipur switch block (nil = no fork, 0 = already on jaipur)
	DelhiBlock                      *big.Int               `json:"delhiBlock"`                 // Delhi switch block (nil = no fork, 0 = already on delhi)
	IndoreBlock                     *big.Int               `json:"indoreBlock"`                // Indore switch block (nil = no fork, 0 = already on indore)
	StateSyncConfirmationDelay      map[string]uint64      `json:"stateSyncConfirmationDelay"` // StateSync Confirmation Delay, in seconds, to calculate `to`
	AhmedabadBlock                  *big.Int               `json:"ahmedabadBlock"`             // Ahmedabad switch block (nil = no fork, 0 = already on ahmedabad)
	BhilaiBlock                     *big.Int               `json:"bhilaiBlock"`                // Bhilai switch block (nil = no fork, 0 = already on bhilai)
	RioBlock                        *big.Int               `json:"rioBlock"`                   // Rio switch block (nil = no fork, 0 = already on rio)
}

// String implements the stringer interface, returning the consensus engine details.
func (c *BorConfig) String() string {
	return "bor"
}

func (c *BorConfig) CalculateProducerDelay(number uint64) uint64 {
	return borKeyValueConfigHelper(c.ProducerDelay, number)
}

func (c *BorConfig) CalculateSprint(number uint64) uint64 {
	return borKeyValueConfigHelper(c.Sprint, number)
}

func (c *BorConfig) CalculateBackupMultiplier(number uint64) uint64 {
	return borKeyValueConfigHelper(c.BackupMultiplier, number)
}

func (c *BorConfig) CalculatePeriod(number uint64) uint64 {
	return borKeyValueConfigHelper(c.Period, number)
}

func (c *BorConfig) IsJaipur(number *big.Int) bool {
	return isBlockForked(c.JaipurBlock, number)
}

func (c *BorConfig) IsDelhi(number *big.Int) bool {
	return isBlockForked(c.DelhiBlock, number)
}

func (c *BorConfig) IsIndore(number *big.Int) bool {
	return isBlockForked(c.IndoreBlock, number)
}

func (c *BorConfig) CalculateStateSyncDelay(number uint64) uint64 {
	return borKeyValueConfigHelper(c.StateSyncConfirmationDelay, number)
}

func (c *BorConfig) IsAhmedabad(number *big.Int) bool {
	return isBlockForked(c.AhmedabadBlock, number)
}

func (c *BorConfig) IsBhilai(number *big.Int) bool {
	return isBlockForked(c.BhilaiBlock, number)
}

func (c *BorConfig) IsRio(number *big.Int) bool {
	return isBlockForked(c.RioBlock, number)
}

// // TODO: modify this function once the block number is finalized
// func (c *BorConfig) IsNapoli(number *big.Int) bool {
// 	if c.NapoliBlock != nil {
// 		if c.NapoliBlock.Cmp(big.NewInt(0)) == 0 {
// 			return false
// 		}
// 	}

// 	return isBlockForked(c.NapoliBlock, number)
// }

func (c *BorConfig) IsSprintStart(number uint64) bool {
	return number%c.CalculateSprint(number) == 0
}

func borKeyValueConfigHelper[T uint64 | string](field map[string]T, number uint64) T {
	keys := make([]uint64, 0, len(field))
	fieldUint := make(map[uint64]T)

	for k, v := range field {
		keyUint, err := strconv.ParseUint(k, 10, 64)
		if err != nil {
			panic(err)
		}

		keys = append(keys, keyUint)

		fieldUint[keyUint] = v
	}

	sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })

	for i := 0; i < len(keys)-1; i++ {
		if number >= keys[i] && number < keys[i+1] {
			return fieldUint[keys[i]]
		}
	}

	return fieldUint[keys[len(keys)-1]]
}

func (c *BorConfig) CalculateBurntContract(number uint64) string {
	return borKeyValueConfigHelper(c.BurntContract, number)
}

func (c *BorConfig) CalculateCoinbase(number uint64) string {
	if c.Coinbase != nil {
		return borKeyValueConfigHelper(c.Coinbase, number)
	} else {
		return common.Address{}.Hex()
	}
}

func (c *BorConfig) GetOverrideStateSyncRecord(block uint64) (int, bool) {
	for _, r := range c.OverrideStateSyncRecordsInRange {
		if block >= r.StartBlock && block <= r.EndBlock {
			return r.Value, true
		}
	}
	return 0, false
}

// Description returns a human-readable description of ChainConfig.
func (c *ChainConfig) Description() string {
	var banner string

	// Create some basic network config output
	network := NetworkNames[c.ChainID.String()]
	if network == "" {
		network = "unknown"
	}

	banner += fmt.Sprintf("Chain ID:  %v (%s)\n", c.ChainID, network)

	switch {
	case c.Ethash != nil:
		banner += "Consensus: Beacon (proof-of-stake), merged from Ethash (proof-of-work)\n"
	case c.Clique != nil:
		banner += "Consensus: Beacon (proof-of-stake), merged from Clique (proof-of-authority)\n"
	case c.Bor != nil:
		banner += "Consensus: Bor (proof-of-stake), merged from Ethash (proof-of-work)\n"
	default:
		banner += "Consensus: unknown\n"
	}

	banner += "\n"

	// Create a list of forks with a short description of them. Forks that only
	// makes sense for mainnet should be optional at printing to avoid bloating
	// the output for testnets and private networks.
	banner += "Pre-Merge hard forks (block based):\n"
	banner += fmt.Sprintf(" - Homestead:                   #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/homestead.md)\n", c.HomesteadBlock)

	if c.DAOForkBlock != nil {
		banner += fmt.Sprintf(" - DAO Fork:                    #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/dao-fork.md)\n", c.DAOForkBlock)
	}

	banner += fmt.Sprintf(" - Tangerine Whistle (EIP 150): #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/tangerine-whistle.md)\n", c.EIP150Block)
	banner += fmt.Sprintf(" - Spurious Dragon/1 (EIP 155): #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)\n", c.EIP155Block)
	banner += fmt.Sprintf(" - Spurious Dragon/2 (EIP 158): #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)\n", c.EIP155Block)
	banner += fmt.Sprintf(" - Byzantium:                   #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/byzantium.md)\n", c.ByzantiumBlock)
	banner += fmt.Sprintf(" - Constantinople:              #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/constantinople.md)\n", c.ConstantinopleBlock)
	banner += fmt.Sprintf(" - Petersburg:                  #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/petersburg.md)\n", c.PetersburgBlock)
	banner += fmt.Sprintf(" - Istanbul:                    #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/istanbul.md)\n", c.IstanbulBlock)

	if c.MuirGlacierBlock != nil {
		banner += fmt.Sprintf(" - Muir Glacier:                #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/muir-glacier.md)\n", c.MuirGlacierBlock)
	}

	banner += fmt.Sprintf(" - Berlin:                      #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/berlin.md)\n", c.BerlinBlock)
	banner += fmt.Sprintf(" - London:                      #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/london.md)\n", c.LondonBlock)

	if c.ArrowGlacierBlock != nil {
		banner += fmt.Sprintf(" - Arrow Glacier:               #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/arrow-glacier.md)\n", c.ArrowGlacierBlock)
	}

	if c.GrayGlacierBlock != nil {
		banner += fmt.Sprintf(" - Gray Glacier:                #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/gray-glacier.md)\n", c.GrayGlacierBlock)
	}

	banner += "\n"

	// Add a special section for the merge as it's non-obvious
	banner += "Merge configured:\n"
	banner += " - Hard-fork specification:    https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md\n"
	banner += " - Network known to be merged\n"
	banner += fmt.Sprintf(" - Total terminal difficulty:  %v\n", c.TerminalTotalDifficulty)
	if c.MergeNetsplitBlock != nil {
		banner += fmt.Sprintf(" - Merge netsplit block:       #%-8v\n", c.MergeNetsplitBlock)
	}

	banner += "\n"

	// Create a list of forks post-merge
	banner += "Post-Merge hard forks (block based):\n"
	if c.ShanghaiBlock != nil {
		banner += fmt.Sprintf(" - Shanghai:                    #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md)\n", c.ShanghaiBlock)
	}

	if c.CancunBlock != nil {
		banner += fmt.Sprintf(" - Cancun:                      #%-8v\n", c.CancunBlock)
	}
	if c.PragueBlock != nil {
		banner += fmt.Sprintf(" - Prague:                      #%-8v\n", c.PragueBlock)
	}
	if c.VerkleBlock != nil {
		banner += fmt.Sprintf(" - Verkle:                      @%-10v\n", *c.VerkleBlock)
	}
	if c.OsakaBlock != nil {
		banner += fmt.Sprintf(" - Osaka:                      #%-8v\n", *c.OsakaBlock)
	}
	return banner
}

// BlobConfig specifies the target and max blobs per block for the associated fork.
type BlobConfig struct {
	Target         int    `json:"target"`
	Max            int    `json:"max"`
	UpdateFraction uint64 `json:"baseFeeUpdateFraction"`
}

// BlobScheduleConfig determines target and max number of blobs allow per fork.
type BlobScheduleConfig struct {
	Cancun *BlobConfig `json:"cancun,omitempty"`
	Prague *BlobConfig `json:"prague,omitempty"`
	Osaka  *BlobConfig `json:"osaka,omitempty"`
	Verkle *BlobConfig `json:"verkle,omitempty"`
}

// IsHomestead returns whether num is either equal to the homestead block or greater.
func (c *ChainConfig) IsHomestead(num *big.Int) bool {
	return isBlockForked(c.HomesteadBlock, num)
}

// IsDAOFork returns whether num is either equal to the DAO fork block or greater.
func (c *ChainConfig) IsDAOFork(num *big.Int) bool {
	return isBlockForked(c.DAOForkBlock, num)
}

// IsEIP150 returns whether num is either equal to the EIP150 fork block or greater.
func (c *ChainConfig) IsEIP150(num *big.Int) bool {
	return isBlockForked(c.EIP150Block, num)
}

// IsEIP155 returns whether num is either equal to the EIP155 fork block or greater.
func (c *ChainConfig) IsEIP155(num *big.Int) bool {
	return isBlockForked(c.EIP155Block, num)
}

// IsEIP158 returns whether num is either equal to the EIP158 fork block or greater.
func (c *ChainConfig) IsEIP158(num *big.Int) bool {
	return isBlockForked(c.EIP158Block, num)
}

// IsByzantium returns whether num is either equal to the Byzantium fork block or greater.
func (c *ChainConfig) IsByzantium(num *big.Int) bool {
	return isBlockForked(c.ByzantiumBlock, num)
}

// IsConstantinople returns whether num is either equal to the Constantinople fork block or greater.
func (c *ChainConfig) IsConstantinople(num *big.Int) bool {
	return isBlockForked(c.ConstantinopleBlock, num)
}

// IsMuirGlacier returns whether num is either equal to the Muir Glacier (EIP-2384) fork block or greater.
func (c *ChainConfig) IsMuirGlacier(num *big.Int) bool {
	return isBlockForked(c.MuirGlacierBlock, num)
}

// IsPetersburg returns whether num is either
// - equal to or greater than the PetersburgBlock fork block,
// - OR is nil, and Constantinople is active
func (c *ChainConfig) IsPetersburg(num *big.Int) bool {
	return isBlockForked(c.PetersburgBlock, num) || c.PetersburgBlock == nil && isBlockForked(c.ConstantinopleBlock, num)
}

// IsIstanbul returns whether num is either equal to the Istanbul fork block or greater.
func (c *ChainConfig) IsIstanbul(num *big.Int) bool {
	return isBlockForked(c.IstanbulBlock, num)
}

// IsBerlin returns whether num is either equal to the Berlin fork block or greater.
func (c *ChainConfig) IsBerlin(num *big.Int) bool {
	return isBlockForked(c.BerlinBlock, num)
}

// IsLondon returns whether num is either equal to the London fork block or greater.
func (c *ChainConfig) IsLondon(num *big.Int) bool {
	return isBlockForked(c.LondonBlock, num)
}

// IsArrowGlacier returns whether num is either equal to the Arrow Glacier (EIP-4345) fork block or greater.
func (c *ChainConfig) IsArrowGlacier(num *big.Int) bool {
	return isBlockForked(c.ArrowGlacierBlock, num)
}

// IsGrayGlacier returns whether num is either equal to the Gray Glacier (EIP-5133) fork block or greater.
func (c *ChainConfig) IsGrayGlacier(num *big.Int) bool {
	return isBlockForked(c.GrayGlacierBlock, num)
}

// IsTerminalPoWBlock returns whether the given block is the last block of PoW stage.
func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *big.Int) bool {
	if c.TerminalTotalDifficulty == nil {
		return false
	}

	return parentTotalDiff.Cmp(c.TerminalTotalDifficulty) < 0 && totalDiff.Cmp(c.TerminalTotalDifficulty) >= 0
}

// IsShanghai returns whether num is either equal to the Shanghai fork block or greater.
func (c *ChainConfig) IsShanghai(num *big.Int) bool {
	return isBlockForked(c.ShanghaiBlock, num)
}

// IsCancun returns whether num is either equal to the Cancun fork block or greater.
func (c *ChainConfig) IsCancun(num *big.Int) bool {
	return isBlockForked(c.CancunBlock, num)
}

// IsPrague returns whether num is either equal to the Prague fork block or greater.
func (c *ChainConfig) IsPrague(num *big.Int) bool {
	return isBlockForked(c.PragueBlock, num)
}

// IsVerkle returns whether num is either equal to the Verkle fork block or greater.
func (c *ChainConfig) IsVerkle(num *big.Int) bool {
	return c.IsLondon(num) && isBlockForked(c.VerkleBlock, num)
}

// IsOsaka returns whether num is either equal to the Osaka fork block or greater.
func (c *ChainConfig) IsOsaka(num *big.Int) bool {
	return c.IsLondon(num) && isBlockForked(c.OsakaBlock, num)
}

// IsVerkleGenesis checks whether the verkle fork is activated at the genesis block.
//
// Verkle mode is considered enabled if the verkle fork time is configured,
// regardless of whether the local time has surpassed the fork activation time.
// This is a temporary workaround for verkle devnet testing, where verkle is
// activated at genesis, and the configured activation date has already passed.
//
// In production networks (mainnet and public testnets), verkle activation
// always occurs after the genesis block, making this function irrelevant in
// those cases.
func (c *ChainConfig) IsVerkleGenesis() bool {
	return c.EnableVerkleAtGenesis
}

// IsEIP4762 returns whether eip 4762 has been activated at given block.
func (c *ChainConfig) IsEIP4762(num *big.Int, time uint64) bool {
	return c.IsVerkle(num)
}

// CheckCompatible checks whether scheduled fork transitions have been imported
// with a mismatching chain configuration.
func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, time uint64) *ConfigCompatError {
	var (
		bhead = new(big.Int).SetUint64(height)
		btime = time
	)
	// Iterate checkCompatible to find the lowest conflict.
	var lasterr *ConfigCompatError

	for {
		err := c.checkCompatible(newcfg, bhead, btime)
		if err == nil || (lasterr != nil && err.RewindToBlock == lasterr.RewindToBlock && err.RewindToTime == lasterr.RewindToTime) {
			break
		}

		lasterr = err

		if err.RewindToTime > 0 {
			btime = err.RewindToTime
		} else {
			bhead.SetUint64(err.RewindToBlock)
		}
	}

	return lasterr
}

// CheckConfigForkOrder checks that we don't "skip" any forks, geth isn't pluggable enough
// to guarantee that forks can be implemented in a different order than on official networks
func (c *ChainConfig) CheckConfigForkOrder() error {
	type fork struct {
		name      string
		block     *big.Int // forks up to - and including the merge - were defined with block numbers
		timestamp *uint64  // forks after the merge are scheduled using timestamps
		optional  bool     // if true, the fork may be nil and next fork is still allowed
	}

	var lastFork fork
	for _, cur := range []fork{
		{name: "homesteadBlock", block: c.HomesteadBlock},
		{name: "daoForkBlock", block: c.DAOForkBlock, optional: true},
		{name: "eip150Block", block: c.EIP150Block},
		{name: "eip155Block", block: c.EIP155Block},
		{name: "eip158Block", block: c.EIP158Block},
		{name: "byzantiumBlock", block: c.ByzantiumBlock},
		{name: "constantinopleBlock", block: c.ConstantinopleBlock},
		{name: "petersburgBlock", block: c.PetersburgBlock},
		{name: "istanbulBlock", block: c.IstanbulBlock},
		{name: "muirGlacierBlock", block: c.MuirGlacierBlock, optional: true},
		{name: "berlinBlock", block: c.BerlinBlock},
		{name: "londonBlock", block: c.LondonBlock},
		{name: "arrowGlacierBlock", block: c.ArrowGlacierBlock, optional: true},
		{name: "grayGlacierBlock", block: c.GrayGlacierBlock, optional: true},
		{name: "mergeNetsplitBlock", block: c.MergeNetsplitBlock, optional: true},
		{name: "shanghaiBlock", block: c.ShanghaiBlock},
		{name: "cancunBlock", block: c.CancunBlock, optional: true},
		{name: "pragueBlock", block: c.PragueBlock, optional: true},
		{name: "osakaBlock", block: c.OsakaBlock, optional: true},
		{name: "verkleBlock", block: c.VerkleBlock, optional: true},
	} {
		if lastFork.name != "" {
			switch {
			// Non-optional forks must all be present in the chain config up to the last defined fork
			case lastFork.block == nil && lastFork.timestamp == nil && (cur.block != nil || cur.timestamp != nil):
				if cur.block != nil {
					return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at block %v",
						lastFork.name, cur.name, cur.block)
				} else {
					return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at timestamp %v",
						lastFork.name, cur.name, *cur.timestamp)
				}

			// Fork (whether defined by block or timestamp) must follow the fork definition sequence
			case (lastFork.block != nil && cur.block != nil) || (lastFork.timestamp != nil && cur.timestamp != nil):
				if lastFork.block != nil && lastFork.block.Cmp(cur.block) > 0 {
					return fmt.Errorf("unsupported fork ordering: %v enabled at block %v, but %v enabled at block %v",
						lastFork.name, lastFork.block, cur.name, cur.block)
				} else if lastFork.timestamp != nil && *lastFork.timestamp > *cur.timestamp {
					return fmt.Errorf("unsupported fork ordering: %v enabled at timestamp %v, but %v enabled at timestamp %v",
						lastFork.name, *lastFork.timestamp, cur.name, *cur.timestamp)
				}

				// Timestamp based forks can follow block based ones, but not the other way around
				if lastFork.timestamp != nil && cur.block != nil {
					return fmt.Errorf("unsupported fork ordering: %v used timestamp ordering, but %v reverted to block ordering",
						lastFork.name, cur.name)
				}
			}
		}
		// If it was optional and not set, then ignore it
		if !cur.optional || (cur.block != nil || cur.timestamp != nil) {
			lastFork = cur
		}
	}

	// Check that all forks with blobs explicitly define the blob schedule configuration.
	bsc := c.BlobScheduleConfig
	if bsc == nil {
		bsc = new(BlobScheduleConfig)
	}
	for _, cur := range []struct {
		name      string
		timestamp *uint64
		config    *BlobConfig
	}{
		{name: "cancun", timestamp: nil, config: bsc.Cancun},
		{name: "prague", timestamp: nil, config: bsc.Prague},
		{name: "osaka", timestamp: nil, config: bsc.Osaka},
	} {
		if cur.config != nil {
			if err := cur.config.validate(); err != nil {
				return fmt.Errorf("invalid chain configuration in blobSchedule for fork %q: %v", cur.name, err)
			}
		}
		if cur.timestamp != nil {
			// If the fork is configured, a blob schedule must be defined for it.
			if cur.config == nil {
				return fmt.Errorf("invalid chain configuration: missing entry for fork %q in blobSchedule", cur.name)
			}
		}
	}
	return nil
}

func (bc *BlobConfig) validate() error {
	if bc.Max < 0 {
		return errors.New("max < 0")
	}
	if bc.Target < 0 {
		return errors.New("target < 0")
	}
	if bc.UpdateFraction == 0 {
		return errors.New("update fraction must be defined and non-zero")
	}
	return nil
}

func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, headTimestamp uint64) *ConfigCompatError {
	if isForkBlockIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, headNumber) {
		return newBlockCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock)
	}

	if isForkBlockIncompatible(c.DAOForkBlock, newcfg.DAOForkBlock, headNumber) {
		return newBlockCompatError("DAO fork block", c.DAOForkBlock, newcfg.DAOForkBlock)
	}

	if c.IsDAOFork(headNumber) && c.DAOForkSupport != newcfg.DAOForkSupport {
		return newBlockCompatError("DAO fork support flag", c.DAOForkBlock, newcfg.DAOForkBlock)
	}

	if isForkBlockIncompatible(c.EIP150Block, newcfg.EIP150Block, headNumber) {
		return newBlockCompatError("EIP150 fork block", c.EIP150Block, newcfg.EIP150Block)
	}

	if isForkBlockIncompatible(c.EIP155Block, newcfg.EIP155Block, headNumber) {
		return newBlockCompatError("EIP155 fork block", c.EIP155Block, newcfg.EIP155Block)
	}

	if isForkBlockIncompatible(c.EIP158Block, newcfg.EIP158Block, headNumber) {
		return newBlockCompatError("EIP158 fork block", c.EIP158Block, newcfg.EIP158Block)
	}

	if c.IsEIP158(headNumber) && !configBlockEqual(c.ChainID, newcfg.ChainID) {
		return newBlockCompatError("EIP158 chain ID", c.EIP158Block, newcfg.EIP158Block)
	}

	if isForkBlockIncompatible(c.ByzantiumBlock, newcfg.ByzantiumBlock, headNumber) {
		return newBlockCompatError("Byzantium fork block", c.ByzantiumBlock, newcfg.ByzantiumBlock)
	}

	if isForkBlockIncompatible(c.ConstantinopleBlock, newcfg.ConstantinopleBlock, headNumber) {
		return newBlockCompatError("Constantinople fork block", c.ConstantinopleBlock, newcfg.ConstantinopleBlock)
	}

	if isForkBlockIncompatible(c.PetersburgBlock, newcfg.PetersburgBlock, headNumber) {
		// the only case where we allow Petersburg to be set in the past is if it is equal to Constantinople
		// mainly to satisfy fork ordering requirements which state that Petersburg fork be set if Constantinople fork is set
		if isForkBlockIncompatible(c.ConstantinopleBlock, newcfg.PetersburgBlock, headNumber) {
			return newBlockCompatError("Petersburg fork block", c.PetersburgBlock, newcfg.PetersburgBlock)
		}
	}

	if isForkBlockIncompatible(c.IstanbulBlock, newcfg.IstanbulBlock, headNumber) {
		return newBlockCompatError("Istanbul fork block", c.IstanbulBlock, newcfg.IstanbulBlock)
	}

	if isForkBlockIncompatible(c.MuirGlacierBlock, newcfg.MuirGlacierBlock, headNumber) {
		return newBlockCompatError("Muir Glacier fork block", c.MuirGlacierBlock, newcfg.MuirGlacierBlock)
	}

	if isForkBlockIncompatible(c.BerlinBlock, newcfg.BerlinBlock, headNumber) {
		return newBlockCompatError("Berlin fork block", c.BerlinBlock, newcfg.BerlinBlock)
	}

	if isForkBlockIncompatible(c.LondonBlock, newcfg.LondonBlock, headNumber) {
		return newBlockCompatError("London fork block", c.LondonBlock, newcfg.LondonBlock)
	}

	if isForkBlockIncompatible(c.ArrowGlacierBlock, newcfg.ArrowGlacierBlock, headNumber) {
		return newBlockCompatError("Arrow Glacier fork block", c.ArrowGlacierBlock, newcfg.ArrowGlacierBlock)
	}

	if isForkBlockIncompatible(c.GrayGlacierBlock, newcfg.GrayGlacierBlock, headNumber) {
		return newBlockCompatError("Gray Glacier fork block", c.GrayGlacierBlock, newcfg.GrayGlacierBlock)
	}

	if isForkBlockIncompatible(c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock, headNumber) {
		return newBlockCompatError("Merge netsplit fork block", c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock)
	}

	if isForkBlockIncompatible(c.ShanghaiBlock, newcfg.ShanghaiBlock, headNumber) {
		return newBlockCompatError("Shanghai fork block", c.ShanghaiBlock, newcfg.ShanghaiBlock)
	}

	if isForkBlockIncompatible(c.CancunBlock, newcfg.CancunBlock, headNumber) {
		return newBlockCompatError("Cancun fork block", c.CancunBlock, newcfg.CancunBlock)
	}

	if isForkBlockIncompatible(c.PragueBlock, newcfg.PragueBlock, headNumber) {
		return newBlockCompatError("Prague fork block", c.PragueBlock, newcfg.PragueBlock)
	}
	if isForkBlockIncompatible(c.VerkleBlock, newcfg.VerkleBlock, headNumber) {
		return newBlockCompatError("Verkle fork timestamp", c.VerkleBlock, newcfg.VerkleBlock)
	}

	if isForkBlockIncompatible(c.OsakaBlock, newcfg.OsakaBlock, headNumber) {
		return newBlockCompatError("Osaka fork block", c.OsakaBlock, newcfg.OsakaBlock)
	}

	return nil
}

// BaseFeeChangeDenominator bounds the amount the base fee can change between blocks.
func (c *ChainConfig) BaseFeeChangeDenominator() uint64 {
	return DefaultBaseFeeChangeDenominator
}

// ElasticityMultiplier bounds the maximum gas limit an EIP-1559 block may have.
func (c *ChainConfig) ElasticityMultiplier() uint64 {
	return DefaultElasticityMultiplier
}

// LatestFork returns the latest time-based fork that would be active for the given time.
func (c *ChainConfig) LatestFork(time uint64) forks.Fork {
	// Assume last non-time-based fork has passed.
	london := c.LondonBlock

	switch {
	case c.IsPrague(london):
		return forks.Prague
	case c.IsOsaka(london):
		return forks.Osaka
	case c.IsCancun(london):
		return forks.Cancun
	case c.IsShanghai(london):
		return forks.Shanghai
	default:
		return forks.Paris
	}
}

/*
// Timestamp returns the timestamp associated with the fork or returns nil if
// the fork isn't defined or isn't a time-based fork.
func (c *ChainConfig) Timestamp(fork forks.Fork) *uint64 {
	switch {
	case fork == forks.Osaka:
		return c.OsakaTime
	case fork == forks.Prague:
		return c.PragueTime
	case fork == forks.Cancun:
		return c.CancunTime
	case fork == forks.Shanghai:
		return c.ShanghaiTime
	default:
		return nil
	}
}
*/

// isForkBlockIncompatible returns true if a fork scheduled at block s1 cannot be
// rescheduled to block s2 because head is already past the fork.
func isForkBlockIncompatible(s1, s2, head *big.Int) bool {
	return (isBlockForked(s1, head) || isBlockForked(s2, head)) && !configBlockEqual(s1, s2)
}

// isBlockForked returns whether a fork scheduled at block s is active at the
// given head block. Whilst this method is the same as isTimestampForked, they
// are explicitly separate for clearer reading.
func isBlockForked(s, head *big.Int) bool {
	if s == nil || head == nil {
		return false
	}

	return s.Cmp(head) <= 0
}

func configBlockEqual(x, y *big.Int) bool {
	if x == nil {
		return y == nil
	}

	if y == nil {
		return x == nil
	}

	return x.Cmp(y) == 0
}

// ConfigCompatError is raised if the locally-stored blockchain is initialised with a
// ChainConfig that would alter the past.
type ConfigCompatError struct {
	What string

	// block numbers of the stored and new configurations if block based forking
	StoredBlock, NewBlock *big.Int

	// timestamps of the stored and new configurations if time based forking
	StoredTime, NewTime *uint64

	// the block number to which the local chain must be rewound to correct the error
	RewindToBlock uint64

	// the timestamp to which the local chain must be rewound to correct the error
	RewindToTime uint64
}

func newBlockCompatError(what string, storedblock, newblock *big.Int) *ConfigCompatError {
	var rew *big.Int

	switch {
	case storedblock == nil:
		rew = newblock
	case newblock == nil || storedblock.Cmp(newblock) < 0:
		rew = storedblock
	default:
		rew = newblock
	}

	err := &ConfigCompatError{
		What:          what,
		StoredBlock:   storedblock,
		NewBlock:      newblock,
		RewindToBlock: 0,
	}
	if rew != nil && rew.Sign() > 0 {
		err.RewindToBlock = rew.Uint64() - 1
	}

	return err
}

// nolint
func newTimestampCompatError(what string, storedtime, newtime *uint64) *ConfigCompatError {
	var rew *uint64
	switch {
	case storedtime == nil:
		rew = newtime
	case newtime == nil || *storedtime < *newtime:
		rew = storedtime
	default:
		rew = newtime
	}
	err := &ConfigCompatError{
		What:         what,
		StoredTime:   storedtime,
		NewTime:      newtime,
		RewindToTime: 0,
	}
	if rew != nil && *rew != 0 {
		err.RewindToTime = *rew - 1
	}

	return err
}

func (err *ConfigCompatError) Error() string {
	if err.StoredBlock != nil {
		return fmt.Sprintf("mismatching %s in database (have block %d, want block %d, rewindto block %d)", err.What, err.StoredBlock, err.NewBlock, err.RewindToBlock)
	}

	if err.StoredTime == nil && err.NewTime == nil {
		return ""
	} else if err.StoredTime == nil && err.NewTime != nil {
		return fmt.Sprintf("mismatching %s in database (have timestamp nil, want timestamp %d, rewindto timestamp %d)", err.What, *err.NewTime, err.RewindToTime)
	} else if err.StoredTime != nil && err.NewTime == nil {
		return fmt.Sprintf("mismatching %s in database (have timestamp %d, want timestamp nil, rewindto timestamp %d)", err.What, *err.StoredTime, err.RewindToTime)
	}
	return fmt.Sprintf("mismatching %s in database (have timestamp %d, want timestamp %d, rewindto timestamp %d)", err.What, *err.StoredTime, *err.NewTime, err.RewindToTime)
}

// Rules wraps ChainConfig and is merely syntactic sugar or can be used for functions
// that do not have or require information about the block.
//
// Rules is a one time interface meaning that it shouldn't be used in between transition
// phases.
type Rules struct {
	ChainID                                                 *big.Int
	IsHomestead, IsEIP150, IsEIP155, IsEIP158               bool
	IsEIP2929, IsEIP4762                                    bool
	IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
	IsBerlin, IsLondon                                      bool
	IsMerge, IsShanghai, IsCancun, IsPrague, IsOsaka        bool
	IsVerkle                                                bool
}

// Rules ensures c's ChainID is not nil.
func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules {
	chainID := c.ChainID
	if chainID == nil {
		chainID = new(big.Int)
	}
	// disallow setting Merge out of order
	isMerge = isMerge && c.IsLondon(num)
	isVerkle := isMerge && c.IsVerkle(num)
	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),
		IsEIP2929:        c.IsBerlin(num) && !isVerkle,
		IsLondon:         c.IsLondon(num),
		IsMerge:          isMerge,
		IsShanghai:       c.IsShanghai(num),
		IsCancun:         c.IsCancun(num),
		IsPrague:         c.IsPrague(num),
		IsVerkle:         c.IsVerkle(num),
		IsOsaka:          c.IsOsaka(num),
		IsEIP4762:        c.IsVerkle(num),
	}
}
