diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go
index 08d829d7d..63c54b1d8 100644
--- a/cmd/evm/internal/t8ntool/execution.go
+++ b/cmd/evm/internal/t8ntool/execution.go
@@ -138,7 +138,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
 		Transfer:    core.Transfer,
 		Coinbase:    pre.Env.Coinbase,
 		BlockNumber: new(big.Int).SetUint64(pre.Env.Number),
-		Time:        new(big.Int).SetUint64(pre.Env.Timestamp),
+		Time:        pre.Env.Timestamp,
 		Difficulty:  pre.Env.Difficulty,
 		GasLimit:    pre.Env.GasLimit,
 		GetHash:     getHash,
diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go
index 1bd370918..21279e8f0 100644
--- a/cmd/evm/internal/t8ntool/transaction.go
+++ b/cmd/evm/internal/t8ntool/transaction.go
@@ -140,7 +140,7 @@ func Transaction(ctx *cli.Context) error {
 		}
 		// Check intrinsic gas
 		if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil,
-			chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(new(big.Int))); err != nil {
+			chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(0)); err != nil {
 			r.Error = err
 			results = append(results, r)
 			continue
@@ -172,7 +172,7 @@ func Transaction(ctx *cli.Context) error {
 			r.Error = errors.New("gas * maxFeePerGas exceeds 256 bits")
 		}
 		// Check whether the init code size has been exceeded.
-		if chainConfig.IsShanghai(new(big.Int)) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize {
+		if chainConfig.IsShanghai(0) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize {
 			r.Error = errors.New("max initcode size exceeded")
 		}
 		results = append(results, r)
diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go
index 9b1975c05..3a010da9f 100644
--- a/cmd/evm/runner.go
+++ b/cmd/evm/runner.go
@@ -209,7 +209,7 @@ func runCmd(ctx *cli.Context) error {
 		GasPrice:    flags.GlobalBig(ctx, PriceFlag.Name),
 		Value:       flags.GlobalBig(ctx, ValueFlag.Name),
 		Difficulty:  genesisConfig.Difficulty,
-		Time:        new(big.Int).SetUint64(genesisConfig.Timestamp),
+		Time:        genesisConfig.Timestamp,
 		Coinbase:    genesisConfig.Coinbase,
 		BlockNumber: new(big.Int).SetUint64(genesisConfig.Number),
 		EVMConfig: vm.Config{
diff --git a/cmd/geth/config.go b/cmd/geth/config.go
index 9c6fd9baa..61b7ed5ec 100644
--- a/cmd/geth/config.go
+++ b/cmd/geth/config.go
@@ -159,7 +159,8 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
 func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
 	stack, cfg := makeConfigNode(ctx)
 	if ctx.IsSet(utils.OverrideShanghai.Name) {
-		cfg.Eth.OverrideShanghai = flags.GlobalBig(ctx, utils.OverrideShanghai.Name)
+		v := ctx.Uint64(utils.OverrideShanghai.Name)
+		cfg.Eth.OverrideShanghai = &v
 	}
 	backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
 
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index e4a9f2ff7..2bbbc381b 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -267,7 +267,7 @@ var (
 		Value:    2048,
 		Category: flags.EthCategory,
 	}
-	OverrideShanghai = &flags.BigFlag{
+	OverrideShanghai = &cli.Uint64Flag{
 		Name:     "override.shanghai",
 		Usage:    "Manually specify the Shanghai fork timestamp, overriding the bundled setting",
 		Category: flags.EthCategory,
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index 36bfa0752..2f9e604de 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -4275,7 +4275,7 @@ func TestEIP3651(t *testing.T) {
 
 	gspec.Config.BerlinBlock = common.Big0
 	gspec.Config.LondonBlock = common.Big0
-	gspec.Config.ShanghaiTime = common.Big0
+	gspec.Config.ShanghaiTime = u64(0)
 	signer := types.LatestSigner(gspec.Config)
 
 	_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
diff --git a/core/evm.go b/core/evm.go
index e929da25e..35e12338e 100644
--- a/core/evm.go
+++ b/core/evm.go
@@ -61,7 +61,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
 		GetHash:     GetHashFn(header, chain),
 		Coinbase:    beneficiary,
 		BlockNumber: new(big.Int).Set(header.Number),
-		Time:        new(big.Int).SetUint64(header.Time),
+		Time:        header.Time,
 		Difficulty:  new(big.Int).Set(header.Difficulty),
 		BaseFee:     baseFee,
 		GasLimit:    header.GasLimit,
diff --git a/core/forkid/forkid.go b/core/forkid/forkid.go
index 300dca6cf..f536019da 100644
--- a/core/forkid/forkid.go
+++ b/core/forkid/forkid.go
@@ -244,7 +244,7 @@ func gatherForks(config *params.ChainConfig) ([]uint64, []uint64) {
 	// Gather all the fork block numbers via reflection
 	kind := reflect.TypeOf(params.ChainConfig{})
 	conf := reflect.ValueOf(config).Elem()
-
+	x := uint64(0)
 	var (
 		forksByBlock []uint64
 		forksByTime  []uint64
@@ -257,15 +257,15 @@ func gatherForks(config *params.ChainConfig) ([]uint64, []uint64) {
 		if !time && !strings.HasSuffix(field.Name, "Block") {
 			continue
 		}
-		if field.Type != reflect.TypeOf(new(big.Int)) {
-			continue
-		}
+
 		// Extract the fork rule block number or timestamp and aggregate it
-		rule := conf.Field(i).Interface().(*big.Int)
-		if rule != nil {
-			if time {
-				forksByTime = append(forksByTime, rule.Uint64())
-			} else {
+		if field.Type == reflect.TypeOf(&x) {
+			if rule := conf.Field(i).Interface().(*uint64); rule != nil {
+				forksByTime = append(forksByTime, *rule)
+			}
+		}
+		if field.Type == reflect.TypeOf(new(big.Int)) {
+			if rule := conf.Field(i).Interface().(*big.Int); rule != nil {
 				forksByBlock = append(forksByBlock, rule.Uint64())
 			}
 		}
diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go
index 7d6e89c81..c4b46bf41 100644
--- a/core/forkid/forkid_test.go
+++ b/core/forkid/forkid_test.go
@@ -19,7 +19,6 @@ package forkid
 import (
 	"bytes"
 	"math"
-	"math/big"
 	"testing"
 
 	"github.com/ethereum/go-ethereum/common"
@@ -27,12 +26,14 @@ import (
 	"github.com/ethereum/go-ethereum/rlp"
 )
 
+func u64(val uint64) *uint64 { return &val }
+
 // TestCreation tests that different genesis and fork rule combinations result in
 // the correct fork ID.
 func TestCreation(t *testing.T) {
 	// Temporary non-existent scenario TODO(karalabe): delete when Shanghai is enabled
 	timestampedConfig := *params.MainnetChainConfig
-	timestampedConfig.ShanghaiTime = big.NewInt(1668000000)
+	timestampedConfig.ShanghaiTime = u64(1668000000)
 
 	type testcase struct {
 		head uint64
@@ -201,7 +202,7 @@ func TestCreation(t *testing.T) {
 func TestValidation(t *testing.T) {
 	// Temporary non-existent scenario TODO(karalabe): delete when Shanghai is enabled
 	timestampedConfig := *params.MainnetChainConfig
-	timestampedConfig.ShanghaiTime = big.NewInt(1668000000)
+	timestampedConfig.ShanghaiTime = u64(1668000000)
 
 	tests := []struct {
 		config *params.ChainConfig
diff --git a/core/genesis.go b/core/genesis.go
index 47974f63a..b4f49a1e1 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -269,7 +269,7 @@ func (e *GenesisMismatchError) Error() string {
 
 // ChainOverrides contains the changes to chain config.
 type ChainOverrides struct {
-	OverrideShanghai *big.Int
+	OverrideShanghai *uint64
 }
 
 // SetupGenesisBlock writes or updates the genesis block in db.
diff --git a/core/state_processor_test.go b/core/state_processor_test.go
index 400ccd318..c91adc36e 100644
--- a/core/state_processor_test.go
+++ b/core/state_processor_test.go
@@ -35,6 +35,8 @@ import (
 	"golang.org/x/crypto/sha3"
 )
 
+func u64(val uint64) *uint64 { return &val }
+
 // TestStateProcessorErrors tests the output from the 'core' errors
 // as defined in core/error.go. These errors are generated when the
 // blockchain imports bad blocks, meaning blocks which have valid headers but
@@ -327,7 +329,7 @@ func TestStateProcessorErrors(t *testing.T) {
 					ArrowGlacierBlock:   big.NewInt(0),
 					GrayGlacierBlock:    big.NewInt(0),
 					MergeNetsplitBlock:  big.NewInt(0),
-					ShanghaiTime:        big.NewInt(0),
+					ShanghaiTime:        u64(0),
 				},
 				Alloc: GenesisAlloc{
 					common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{
diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go
index 3e4eb21cf..6b878ed58 100644
--- a/core/txpool/txpool.go
+++ b/core/txpool/txpool.go
@@ -1312,7 +1312,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
 	pool.istanbul = pool.chainconfig.IsIstanbul(next)
 	pool.eip2718 = pool.chainconfig.IsBerlin(next)
 	pool.eip1559 = pool.chainconfig.IsLondon(next)
-	pool.shanghai = pool.chainconfig.IsShanghai(big.NewInt(time.Now().Unix()))
+	pool.shanghai = pool.chainconfig.IsShanghai(uint64(time.Now().Unix()))
 }
 
 // promoteExecutables moves transactions that have become processable from the
diff --git a/core/vm/evm.go b/core/vm/evm.go
index 149e9f761..f6a1557e8 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -71,7 +71,7 @@ type BlockContext struct {
 	Coinbase    common.Address // Provides information for COINBASE
 	GasLimit    uint64         // Provides information for GASLIMIT
 	BlockNumber *big.Int       // Provides information for NUMBER
-	Time        *big.Int       // Provides information for TIME
+	Time        uint64         // Provides information for TIME
 	Difficulty  *big.Int       // Provides information for DIFFICULTY
 	BaseFee     *big.Int       // Provides information for BASEFEE
 	Random      *common.Hash   // Provides information for PREVRANDAO
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 8fa2fc57e..886ff6323 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -460,8 +460,7 @@ func opCoinbase(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
 }
 
 func opTimestamp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
-	v, _ := uint256.FromBig(interpreter.evm.Context.Time)
-	scope.Stack.push(v)
+	scope.Stack.push(new(uint256.Int).SetUint64(interpreter.evm.Context.Time))
 	return nil, nil
 }
 
diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go
index a330825b1..15a1f1a1b 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/runtime/runtime.go
@@ -19,7 +19,6 @@ package runtime
 import (
 	"math"
 	"math/big"
-	"time"
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/rawdb"
@@ -37,7 +36,7 @@ type Config struct {
 	Origin      common.Address
 	Coinbase    common.Address
 	BlockNumber *big.Int
-	Time        *big.Int
+	Time        uint64
 	GasLimit    uint64
 	GasPrice    *big.Int
 	Value       *big.Int
@@ -74,9 +73,6 @@ func setDefaults(cfg *Config) {
 	if cfg.Difficulty == nil {
 		cfg.Difficulty = new(big.Int)
 	}
-	if cfg.Time == nil {
-		cfg.Time = big.NewInt(time.Now().Unix())
-	}
 	if cfg.GasLimit == 0 {
 		cfg.GasLimit = math.MaxUint64
 	}
diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go
index 868d41e50..607259106 100644
--- a/core/vm/runtime/runtime_test.go
+++ b/core/vm/runtime/runtime_test.go
@@ -48,9 +48,6 @@ func TestDefaults(t *testing.T) {
 		t.Error("expected difficulty to be non nil")
 	}
 
-	if cfg.Time == nil {
-		t.Error("expected time to be non nil")
-	}
 	if cfg.GasLimit == 0 {
 		t.Error("didn't expect gaslimit to be zero")
 	}
@@ -174,7 +171,7 @@ func benchmarkEVM_Create(bench *testing.B, code string) {
 		State:       statedb,
 		GasLimit:    10000000,
 		Difficulty:  big.NewInt(0x200000),
-		Time:        new(big.Int).SetUint64(0),
+		Time:        0,
 		Coinbase:    common.Address{},
 		BlockNumber: new(big.Int).SetUint64(1),
 		ChainConfig: &params.ChainConfig{
diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go
index 04ef21f49..db686c5d0 100644
--- a/eth/ethconfig/config.go
+++ b/eth/ethconfig/config.go
@@ -18,7 +18,6 @@
 package ethconfig
 
 import (
-	"math/big"
 	"os"
 	"os/user"
 	"path/filepath"
@@ -207,7 +206,7 @@ type Config struct {
 	CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"`
 
 	// OverrideShanghai (TODO: remove after the fork)
-	OverrideShanghai *big.Int `toml:",omitempty"`
+	OverrideShanghai *uint64 `toml:",omitempty"`
 }
 
 // CreateConsensusEngine creates a consensus engine for the given chain configuration.
diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go
index 3506d39d5..b7255a242 100644
--- a/eth/ethconfig/gen_config.go
+++ b/eth/ethconfig/gen_config.go
@@ -3,7 +3,6 @@
 package ethconfig
 
 import (
-	"math/big"
 	"time"
 
 	"github.com/ethereum/go-ethereum/common"
@@ -61,7 +60,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
 		RPCTxFeeCap             float64
 		Checkpoint              *params.TrustedCheckpoint      `toml:",omitempty"`
 		CheckpointOracle        *params.CheckpointOracleConfig `toml:",omitempty"`
-		OverrideShanghai        *big.Int                       `toml:",omitempty"`
+		OverrideShanghai        *uint64                        `toml:",omitempty"`
 	}
 	var enc Config
 	enc.Genesis = c.Genesis
@@ -155,7 +154,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
 		RPCTxFeeCap             *float64
 		Checkpoint              *params.TrustedCheckpoint      `toml:",omitempty"`
 		CheckpointOracle        *params.CheckpointOracleConfig `toml:",omitempty"`
-		OverrideShanghai        *big.Int                       `toml:",omitempty"`
+		OverrideShanghai        *uint64                        `toml:",omitempty"`
 	}
 	var dec Config
 	if err := unmarshal(&dec); err != nil {
diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go
index 5cfb5b33c..d240e9a4b 100644
--- a/eth/tracers/internal/tracetest/calltrace_test.go
+++ b/eth/tracers/internal/tracetest/calltrace_test.go
@@ -133,7 +133,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
 					Transfer:    core.Transfer,
 					Coinbase:    test.Context.Miner,
 					BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
-					Time:        new(big.Int).SetUint64(uint64(test.Context.Time)),
+					Time:        uint64(test.Context.Time),
 					Difficulty:  (*big.Int)(test.Context.Difficulty),
 					GasLimit:    uint64(test.Context.GasLimit),
 					BaseFee:     test.Genesis.BaseFee,
@@ -234,7 +234,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
 		Transfer:    core.Transfer,
 		Coinbase:    test.Context.Miner,
 		BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
-		Time:        new(big.Int).SetUint64(uint64(test.Context.Time)),
+		Time:        uint64(test.Context.Time),
 		Difficulty:  (*big.Int)(test.Context.Difficulty),
 		GasLimit:    uint64(test.Context.GasLimit),
 	}
@@ -288,7 +288,7 @@ func TestZeroValueToNotExitCall(t *testing.T) {
 		Transfer:    core.Transfer,
 		Coinbase:    common.Address{},
 		BlockNumber: new(big.Int).SetUint64(8000000),
-		Time:        new(big.Int).SetUint64(5),
+		Time:        5,
 		Difficulty:  big.NewInt(0x30000),
 		GasLimit:    uint64(6000000),
 	}
diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go
index 2fee7d6fb..03f06311a 100644
--- a/eth/tracers/internal/tracetest/prestate_test.go
+++ b/eth/tracers/internal/tracetest/prestate_test.go
@@ -103,7 +103,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
 					Transfer:    core.Transfer,
 					Coinbase:    test.Context.Miner,
 					BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
-					Time:        new(big.Int).SetUint64(uint64(test.Context.Time)),
+					Time:        uint64(test.Context.Time),
 					Difficulty:  (*big.Int)(test.Context.Difficulty),
 					GasLimit:    uint64(test.Context.GasLimit),
 					BaseFee:     test.Genesis.BaseFee,
diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go
index 12e01abae..6cd5a022b 100644
--- a/eth/tracers/tracers_test.go
+++ b/eth/tracers/tracers_test.go
@@ -56,7 +56,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
 		Transfer:    core.Transfer,
 		Coinbase:    common.Address{},
 		BlockNumber: new(big.Int).SetUint64(uint64(5)),
-		Time:        new(big.Int).SetUint64(uint64(5)),
+		Time:        5,
 		Difficulty:  big.NewInt(0xffffffff),
 		GasLimit:    gas,
 		BaseFee:     big.NewInt(8),
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index b6efba079..e0e4278bb 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -920,7 +920,7 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
 type BlockOverrides struct {
 	Number     *hexutil.Big
 	Difficulty *hexutil.Big
-	Time       *hexutil.Big
+	Time       *hexutil.Uint64
 	GasLimit   *hexutil.Uint64
 	Coinbase   *common.Address
 	Random     *common.Hash
@@ -939,7 +939,7 @@ func (diff *BlockOverrides) Apply(blockCtx *vm.BlockContext) {
 		blockCtx.Difficulty = diff.Difficulty.ToInt()
 	}
 	if diff.Time != nil {
-		blockCtx.Time = diff.Time.ToInt()
+		blockCtx.Time = uint64(*diff.Time)
 	}
 	if diff.GasLimit != nil {
 		blockCtx.GasLimit = uint64(*diff.GasLimit)
@@ -1444,7 +1444,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
 	}
 	isPostMerge := header.Difficulty.Cmp(common.Big0) == 0
 	// Retrieve the precompiles since they don't need to be added to the access list
-	precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, new(big.Int).SetUint64(header.Time)))
+	precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, header.Time))
 
 	// Create an initial tracer
 	prevTracer := logger.NewAccessListTracer(nil, args.from(), to, precompiles)
diff --git a/light/txpool.go b/light/txpool.go
index e12f6ef94..e59dc3e77 100644
--- a/light/txpool.go
+++ b/light/txpool.go
@@ -318,7 +318,7 @@ func (pool *TxPool) setNewHead(head *types.Header) {
 	next := new(big.Int).Add(head.Number, big.NewInt(1))
 	pool.istanbul = pool.config.IsIstanbul(next)
 	pool.eip2718 = pool.config.IsBerlin(next)
-	pool.shanghai = pool.config.IsShanghai(big.NewInt(time.Now().Unix()))
+	pool.shanghai = pool.config.IsShanghai(uint64(time.Now().Unix()))
 }
 
 // Stop stops the light transaction pool
diff --git a/params/config.go b/params/config.go
index 41072d3ea..aac439230 100644
--- a/params/config.go
+++ b/params/config.go
@@ -383,7 +383,7 @@ var (
 		Ethash:                        new(EthashConfig),
 		Clique:                        nil,
 	}
-	TestRules = TestChainConfig.Rules(new(big.Int), false, new(big.Int))
+	TestRules = TestChainConfig.Rules(new(big.Int), false, 0)
 )
 
 // NetworkNames are user friendly names to use in the chain spec banner.
@@ -476,9 +476,9 @@ type ChainConfig struct {
 
 	// Fork scheduling was switched from blocks to timestamps here
 
-	ShanghaiTime *big.Int `json:"shanghaiTime,omitempty"` // Shanghai switch time (nil = no fork, 0 = already on shanghai)
-	CancunTime   *big.Int `json:"cancunTime,omitempty"`   // Cancun switch time (nil = no fork, 0 = already on cancun)
-	PragueTime   *big.Int `json:"pragueTime,omitempty"`   // Prague switch time (nil = no fork, 0 = already on prague)
+	ShanghaiTime *uint64 `json:"shanghaiTime,omitempty"` // Shanghai switch time (nil = no fork, 0 = already on shanghai)
+	CancunTime   *uint64 `json:"cancunTime,omitempty"`   // Cancun switch time (nil = no fork, 0 = already on cancun)
+	PragueTime   *uint64 `json:"pragueTime,omitempty"`   // Prague switch time (nil = no fork, 0 = already on prague)
 
 	// TerminalTotalDifficulty is the amount of total difficulty reached by
 	// the network that triggers the consensus upgrade.
@@ -683,17 +683,17 @@ func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *bi
 }
 
 // IsShanghai returns whether time is either equal to the Shanghai fork time or greater.
-func (c *ChainConfig) IsShanghai(time *big.Int) bool {
+func (c *ChainConfig) IsShanghai(time uint64) bool {
 	return isTimestampForked(c.ShanghaiTime, time)
 }
 
 // IsCancun returns whether num is either equal to the Cancun fork time or greater.
-func (c *ChainConfig) IsCancun(time *big.Int) bool {
+func (c *ChainConfig) IsCancun(time uint64) bool {
 	return isTimestampForked(c.CancunTime, time)
 }
 
 // IsPrague returns whether num is either equal to the Prague fork time or greater.
-func (c *ChainConfig) IsPrague(time *big.Int) bool {
+func (c *ChainConfig) IsPrague(time uint64) bool {
 	return isTimestampForked(c.PragueTime, time)
 }
 
@@ -702,7 +702,7 @@ func (c *ChainConfig) IsPrague(time *big.Int) bool {
 func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, time uint64) *ConfigCompatError {
 	var (
 		bhead = new(big.Int).SetUint64(height)
-		btime = new(big.Int).SetUint64(time)
+		btime = time
 	)
 	// Iterate checkCompatible to find the lowest conflict.
 	var lasterr *ConfigCompatError
@@ -714,7 +714,7 @@ func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, time u
 		lasterr = err
 
 		if err.RewindToTime > 0 {
-			btime.SetUint64(err.RewindToTime)
+			btime = err.RewindToTime
 		} else {
 			bhead.SetUint64(err.RewindToBlock)
 		}
@@ -728,7 +728,7 @@ 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 *big.Int // forks after the merge are scheduled using timestamps
+		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
@@ -769,7 +769,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
 				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.Cmp(cur.timestamp) > 0 {
+				} 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)
 				}
@@ -789,7 +789,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
 	return nil
 }
 
-func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, headTimestamp *big.Int) *ConfigCompatError {
+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)
 	}
@@ -895,28 +895,28 @@ func configBlockEqual(x, y *big.Int) bool {
 
 // isForkTimestampIncompatible returns true if a fork scheduled at timestamp s1
 // cannot be rescheduled to timestamp s2 because head is already past the fork.
-func isForkTimestampIncompatible(s1, s2, head *big.Int) bool {
+func isForkTimestampIncompatible(s1, s2 *uint64, head uint64) bool {
 	return (isTimestampForked(s1, head) || isTimestampForked(s2, head)) && !configTimestampEqual(s1, s2)
 }
 
 // isTimestampForked returns whether a fork scheduled at timestamp s is active
 // at the given head timestamp. Whilst this method is the same as isBlockForked,
 // they are explicitly separate for clearer reading.
-func isTimestampForked(s, head *big.Int) bool {
-	if s == nil || head == nil {
+func isTimestampForked(s *uint64, head uint64) bool {
+	if s == nil {
 		return false
 	}
-	return s.Cmp(head) <= 0
+	return *s <= head
 }
 
-func configTimestampEqual(x, y *big.Int) bool {
+func configTimestampEqual(x, y *uint64) bool {
 	if x == nil {
 		return y == nil
 	}
 	if y == nil {
 		return x == nil
 	}
-	return x.Cmp(y) == 0
+	return *x == *y
 }
 
 // ConfigCompatError is raised if the locally-stored blockchain is initialised with a
@@ -928,7 +928,7 @@ type ConfigCompatError struct {
 	StoredBlock, NewBlock *big.Int
 
 	// timestamps of the stored and new configurations if time based forking
-	StoredTime, NewTime *big.Int
+	StoredTime, NewTime *uint64
 
 	// the block number to which the local chain must be rewound to correct the error
 	RewindToBlock uint64
@@ -959,12 +959,12 @@ func newBlockCompatError(what string, storedblock, newblock *big.Int) *ConfigCom
 	return err
 }
 
-func newTimestampCompatError(what string, storedtime, newtime *big.Int) *ConfigCompatError {
-	var rew *big.Int
+func newTimestampCompatError(what string, storedtime, newtime *uint64) *ConfigCompatError {
+	var rew *uint64
 	switch {
 	case storedtime == nil:
 		rew = newtime
-	case newtime == nil || storedtime.Cmp(newtime) < 0:
+	case newtime == nil || *storedtime < *newtime:
 		rew = storedtime
 	default:
 		rew = newtime
@@ -975,8 +975,8 @@ func newTimestampCompatError(what string, storedtime, newtime *big.Int) *ConfigC
 		NewTime:      newtime,
 		RewindToTime: 0,
 	}
-	if rew != nil && rew.Sign() > 0 {
-		err.RewindToTime = rew.Uint64() - 1
+	if rew != nil {
+		err.RewindToTime = *rew - 1
 	}
 	return err
 }
@@ -1002,7 +1002,7 @@ type Rules struct {
 }
 
 // Rules ensures c's ChainID is not nil.
-func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp *big.Int) Rules {
+func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules {
 	chainID := c.ChainID
 	if chainID == nil {
 		chainID = new(big.Int)
diff --git a/params/config_test.go b/params/config_test.go
index 523ba26fd..f3911f433 100644
--- a/params/config_test.go
+++ b/params/config_test.go
@@ -21,8 +21,12 @@ import (
 	"reflect"
 	"testing"
 	"time"
+
+	"github.com/ethereum/go-ethereum/common/math"
 )
 
+func u64(val uint64) *uint64 { return &val }
+
 func TestCheckCompatible(t *testing.T) {
 	type test struct {
 		stored, new   *ChainConfig
@@ -91,19 +95,19 @@ func TestCheckCompatible(t *testing.T) {
 			},
 		},
 		{
-			stored:        &ChainConfig{ShanghaiTime: big.NewInt(10)},
-			new:           &ChainConfig{ShanghaiTime: big.NewInt(20)},
+			stored:        &ChainConfig{ShanghaiTime: u64(10)},
+			new:           &ChainConfig{ShanghaiTime: u64(20)},
 			headTimestamp: 9,
 			wantErr:       nil,
 		},
 		{
-			stored:        &ChainConfig{ShanghaiTime: big.NewInt(10)},
-			new:           &ChainConfig{ShanghaiTime: big.NewInt(20)},
+			stored:        &ChainConfig{ShanghaiTime: u64(10)},
+			new:           &ChainConfig{ShanghaiTime: u64(20)},
 			headTimestamp: 25,
 			wantErr: &ConfigCompatError{
 				What:         "Shanghai fork timestamp",
-				StoredTime:   big.NewInt(10),
-				NewTime:      big.NewInt(20),
+				StoredTime:   u64(10),
+				NewTime:      u64(20),
 				RewindToTime: 9,
 			},
 		},
@@ -116,3 +120,21 @@ func TestCheckCompatible(t *testing.T) {
 		}
 	}
 }
+
+func TestConfigRules(t *testing.T) {
+	c := &ChainConfig{
+		ShanghaiTime: u64(500),
+	}
+	var stamp uint64
+	if r := c.Rules(big.NewInt(0), true, stamp); r.IsShanghai {
+		t.Errorf("expected %v to not be shanghai", stamp)
+	}
+	stamp = 500
+	if r := c.Rules(big.NewInt(0), true, stamp); !r.IsShanghai {
+		t.Errorf("expected %v to be shanghai", stamp)
+	}
+	stamp = math.MaxInt64
+	if r := c.Rules(big.NewInt(0), true, stamp); !r.IsShanghai {
+		t.Errorf("expected %v to be shanghai", stamp)
+	}
+}
diff --git a/tests/init.go b/tests/init.go
index fd0b01508..a36ab4d9d 100644
--- a/tests/init.go
+++ b/tests/init.go
@@ -24,6 +24,8 @@ import (
 	"github.com/ethereum/go-ethereum/params"
 )
 
+func u64(val uint64) *uint64 { return &val }
+
 // Forks table defines supported forks and their chain config.
 var Forks = map[string]*params.ChainConfig{
 	"Frontier": {
@@ -264,7 +266,7 @@ var Forks = map[string]*params.ChainConfig{
 		ArrowGlacierBlock:       big.NewInt(0),
 		MergeNetsplitBlock:      big.NewInt(0),
 		TerminalTotalDifficulty: big.NewInt(0),
-		ShanghaiTime:            big.NewInt(0),
+		ShanghaiTime:            u64(0),
 	},
 }
 
diff --git a/tests/state_test.go b/tests/state_test.go
index 4c5e7b914..a68321e76 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -183,7 +183,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
 				b.Error(err)
 				return
 			}
-			var rules = config.Rules(new(big.Int), false, new(big.Int))
+			var rules = config.Rules(new(big.Int), false, 0)
 
 			vmconfig.ExtraEips = eips
 			block := t.genesis(config).ToBlock()