diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index 171f5df8a81..9ab0840ba5f 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -174,7 +174,7 @@ func (b *SimulatedBackend) emptyPendingBlock() {
b.pendingBlock = blockChain.Blocks[0]
b.pendingReceipts = blockChain.Receipts[0]
b.pendingHeader = blockChain.Headers[0]
- b.gasPool = new(core.GasPool).AddGas(b.pendingHeader.GasLimit).AddBlobGas(b.m.ChainConfig.GetMaxBlobGasPerBlock())
+ b.gasPool = new(core.GasPool).AddGas(b.pendingHeader.GasLimit).AddBlobGas(b.m.ChainConfig.GetMaxBlobGasPerBlock(b.pendingHeader.Time))
if b.pendingReaderTx != nil {
b.pendingReaderTx.Rollback()
}
@@ -721,7 +721,7 @@ func (b *SimulatedBackend) callContract(_ context.Context, call ethereum.CallMsg
txContext := core.NewEVMTxContext(msg)
header := block.Header()
- evmContext := core.NewEVMBlockContext(header, core.GetHashFn(header, b.getHeader), b.m.Engine, nil)
+ evmContext := core.NewEVMBlockContext(header, core.GetHashFn(header, b.getHeader), b.m.Engine, nil, b.m.ChainConfig)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmEnv := vm.NewEVM(evmContext, txContext, statedb, b.m.ChainConfig, vm.Config{})
diff --git a/cmd/devnet/services/polygon/proofgenerator_test.go b/cmd/devnet/services/polygon/proofgenerator_test.go
index 8880de213c0..cd94483ec1e 100644
--- a/cmd/devnet/services/polygon/proofgenerator_test.go
+++ b/cmd/devnet/services/polygon/proofgenerator_test.go
@@ -154,7 +154,7 @@ func (rg *requestGenerator) GetTransactionReceipt(ctx context.Context, hash libc
var usedGas uint64
var usedBlobGas uint64
- gp := new(core.GasPool).AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock())
+ gp := new(core.GasPool).AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock(block.Header().Time))
noopWriter := state.NewNoopWriter()
diff --git a/cmd/state/commands/opcode_tracer.go b/cmd/state/commands/opcode_tracer.go
index 26c2fd61deb..dd15180b4a2 100644
--- a/cmd/state/commands/opcode_tracer.go
+++ b/cmd/state/commands/opcode_tracer.go
@@ -711,7 +711,7 @@ func runBlock(engine consensus.Engine, ibs *state.IntraBlockState, txnWriter sta
chainConfig *chain2.Config, getHeader func(hash libcommon.Hash, number uint64) *types.Header, block *types.Block, vmConfig vm.Config, trace bool, logger log.Logger) (types.Receipts, error) {
header := block.Header()
vmConfig.TraceJumpDest = true
- gp := new(core.GasPool).AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock())
+ gp := new(core.GasPool).AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock(header.Time))
usedGas := new(uint64)
usedBlobGas := new(uint64)
var receipts types.Receipts
diff --git a/cmd/state/exec3/state.go b/cmd/state/exec3/state.go
index 10edbc93423..037d60e00fb 100644
--- a/cmd/state/exec3/state.go
+++ b/cmd/state/exec3/state.go
@@ -194,7 +194,7 @@ func (rw *Worker) RunTxTaskNoLock(txTask *exec22.TxTask) {
blockContext := txTask.EvmBlockContext
if !rw.background {
getHashFn := core.GetHashFn(header, rw.getHeader)
- blockContext = core.NewEVMBlockContext(header, getHashFn, rw.engine, nil /* author */)
+ blockContext = core.NewEVMBlockContext(header, getHashFn, rw.engine, nil /* author */, rw.chainConfig)
}
rw.evm.ResetBetweenBlocks(blockContext, core.NewEVMTxContext(msg), ibs, vmConfig, rules)
diff --git a/consensus/merge/merge.go b/consensus/merge/merge.go
index 40f662c2524..44593172381 100644
--- a/consensus/merge/merge.go
+++ b/consensus/merge/merge.go
@@ -283,7 +283,7 @@ func (s *Merge) verifyHeader(chain consensus.ChainHeaderReader, header, parent *
if err := misc.VerifyPresenceOfCancunHeaderFields(header); err != nil {
return err
}
- expectedExcessBlobGas := misc.CalcExcessBlobGas(chain.Config(), parent)
+ expectedExcessBlobGas := misc.CalcExcessBlobGas(chain.Config(), parent, header.Time)
if *header.ExcessBlobGas != expectedExcessBlobGas {
return fmt.Errorf("invalid excessBlobGas: have %d, want %d", *header.ExcessBlobGas, expectedExcessBlobGas)
}
diff --git a/consensus/misc/eip1559.go b/consensus/misc/eip1559.go
index 697dfc7f770..34e6f10e7a4 100644
--- a/consensus/misc/eip1559.go
+++ b/consensus/misc/eip1559.go
@@ -84,10 +84,17 @@ func (f eip1559Calculator) CurrentFees(chainConfig *chain.Config, db kv.Getter)
}
if currentHeader.ExcessBlobGas != nil {
- excessBlobGas := CalcExcessBlobGas(chainConfig, currentHeader)
- b, err := GetBlobGasPrice(chainConfig, excessBlobGas)
+ var nextHeaderTime = currentHeader.Time + 1 // Speculative - Next header must be at least 1 second ahead
+ parentHeader := rawdb.ReadHeaderByNumber(db, currentHeader.Number.Uint64()-1)
+ if parentHeader != nil {
+ nextHeaderTime = currentHeader.Time + (currentHeader.Time - parentHeader.Time) // This difference should be close enough to seconds per slot
+ }
+ excessBlobGas := CalcExcessBlobGas(chainConfig, currentHeader, nextHeaderTime)
+ b, err := GetBlobGasPrice(chainConfig, excessBlobGas, nextHeaderTime)
if err == nil {
blobFee = b.Uint64()
+ } else {
+ return 0, 0, 0, 0, err
}
}
}
diff --git a/consensus/misc/eip4844.go b/consensus/misc/eip4844.go
index ca40c89d1dd..f35491435b4 100644
--- a/consensus/misc/eip4844.go
+++ b/consensus/misc/eip4844.go
@@ -28,7 +28,8 @@ import (
)
// CalcExcessBlobGas implements calc_excess_blob_gas from EIP-4844
-func CalcExcessBlobGas(config *chain.Config, parent *types.Header) uint64 {
+// Updated for EIP-7691: currentHeaderTime is used to determine the fork, and hence params
+func CalcExcessBlobGas(config *chain.Config, parent *types.Header, currentHeaderTime uint64) uint64 {
var excessBlobGas, blobGasUsed uint64
if parent.ExcessBlobGas != nil {
excessBlobGas = *parent.ExcessBlobGas
@@ -37,10 +38,10 @@ func CalcExcessBlobGas(config *chain.Config, parent *types.Header) uint64 {
blobGasUsed = *parent.BlobGasUsed
}
- if excessBlobGas+blobGasUsed < config.GetTargetBlobGasPerBlock() {
+ if excessBlobGas+blobGasUsed < config.GetTargetBlobGasPerBlock(currentHeaderTime) {
return 0
}
- return excessBlobGas + blobGasUsed - config.GetTargetBlobGasPerBlock()
+ return excessBlobGas + blobGasUsed - config.GetTargetBlobGasPerBlock(currentHeaderTime)
}
// FakeExponential approximates factor * e ** (num / denom) using a taylor expansion
@@ -99,8 +100,8 @@ func VerifyAbsenceOfCancunHeaderFields(header *types.Header) error {
return nil
}
-func GetBlobGasPrice(config *chain.Config, excessBlobGas uint64) (*uint256.Int, error) {
- return FakeExponential(uint256.NewInt(config.GetMinBlobGasPrice()), uint256.NewInt(config.GetBlobGasPriceUpdateFraction()), excessBlobGas)
+func GetBlobGasPrice(config *chain.Config, excessBlobGas uint64, headerTime uint64) (*uint256.Int, error) {
+ return FakeExponential(uint256.NewInt(config.GetMinBlobGasPrice()), uint256.NewInt(config.GetBlobGasPriceUpdateFraction(headerTime)), excessBlobGas)
}
func GetBlobGasUsed(numBlobs int) uint64 {
diff --git a/core/blockchain.go b/core/blockchain.go
index d55b9cdc98f..362a7ee7b0e 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -96,7 +96,7 @@ func ExecuteBlockEphemerally(
usedGas := new(uint64)
usedBlobGas := new(uint64)
gp := new(GasPool)
- gp.AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock())
+ gp.AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock(block.Time()))
if err := InitializeBlockExecution(engine, chainReader, block.Header(), chainConfig, ibs, logger); err != nil {
return nil, err
@@ -265,7 +265,7 @@ func SysCallContract(contract libcommon.Address, data []byte, chainConfig *chain
author = &state.SystemAddress
txContext = NewEVMTxContext(msg)
}
- blockContext := NewEVMBlockContext(header, GetHashFn(header, nil), engine, author)
+ blockContext := NewEVMBlockContext(header, GetHashFn(header, nil), engine, author, chainConfig)
evm := vm.NewEVM(blockContext, txContext, ibs, chainConfig, vmConfig)
ret, _, err := evm.Call(
@@ -299,7 +299,7 @@ func SysCreate(contract libcommon.Address, data []byte, chainConfig chain.Config
// Create a new context to be used in the EVM environment
author := &contract
txContext := NewEVMTxContext(msg)
- blockContext := NewEVMBlockContext(header, GetHashFn(header, nil), nil, author)
+ blockContext := NewEVMBlockContext(header, GetHashFn(header, nil), nil, author, &chainConfig)
evm := vm.NewEVM(blockContext, txContext, ibs, &chainConfig, vmConfig)
ret, _, err := evm.SysCreate(
diff --git a/core/chain_makers.go b/core/chain_makers.go
index 386b9cd4b7a..b6646afdecd 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -600,7 +600,7 @@ func MakeEmptyHeader(parent *types.Header, chainConfig *chain.Config, timestamp
}
if chainConfig.IsCancun(header.Time) {
- excessBlobGas := misc.CalcExcessBlobGas(chainConfig, parent)
+ excessBlobGas := misc.CalcExcessBlobGas(chainConfig, parent, header.Time)
header.ExcessBlobGas = &excessBlobGas
header.BlobGasUsed = new(uint64)
}
diff --git a/core/evm.go b/core/evm.go
index 7534cfc1e13..f20223fc1ff 100644
--- a/core/evm.go
+++ b/core/evm.go
@@ -1,18 +1,21 @@
// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
+// (original work)
+// Copyright 2024 The Erigon Authors
+// (modifications)
+// This file is part of Erigon.
//
-// The go-ethereum library is free software: you can redistribute it and/or modify
+// Erigon 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,
+// Erigon 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 .
+// along with Erigon. If not, see .
package core
@@ -22,16 +25,19 @@ import (
"github.com/holiman/uint256"
+ "github.com/erigontech/erigon-lib/chain"
libcommon "github.com/erigontech/erigon-lib/common"
"github.com/erigontech/erigon/consensus"
"github.com/erigontech/erigon/consensus/merge"
+ "github.com/erigontech/erigon/consensus/misc"
"github.com/erigontech/erigon/core/types"
"github.com/erigontech/erigon/core/vm/evmtypes"
)
// NewEVMBlockContext creates a new context for use in the EVM.
-func NewEVMBlockContext(header *types.Header, blockHashFunc func(n uint64) libcommon.Hash, engine consensus.EngineReader, author *libcommon.Address) evmtypes.BlockContext {
+func NewEVMBlockContext(header *types.Header, blockHashFunc func(n uint64) libcommon.Hash,
+ engine consensus.EngineReader, author *libcommon.Address, config *chain.Config) evmtypes.BlockContext {
// If we don't have an explicit author (i.e. not mining), extract from the header
var beneficiary libcommon.Address
if author == nil {
@@ -54,10 +60,13 @@ func NewEVMBlockContext(header *types.Header, blockHashFunc func(n uint64) libco
*prevRandDao = header.MixDigest
}
- var excessBlobGas *uint64
+ var blobBaseFee *uint256.Int
if header.ExcessBlobGas != nil {
- excessBlobGas = new(uint64)
- *excessBlobGas = *header.ExcessBlobGas
+ var err error
+ blobBaseFee, err = misc.GetBlobGasPrice(config, *header.ExcessBlobGas, header.Time)
+ if err != nil {
+ panic(err)
+ }
}
var transferFunc evmtypes.TransferFunc
@@ -81,7 +90,7 @@ func NewEVMBlockContext(header *types.Header, blockHashFunc func(n uint64) libco
BaseFee: &baseFee,
GasLimit: header.GasLimit,
PrevRanDao: prevRandDao,
- ExcessBlobGas: excessBlobGas,
+ BlobBaseFee: blobBaseFee,
}
}
diff --git a/core/state_processor.go b/core/state_processor.go
index c65a7582ad3..ac393408a9d 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -112,7 +112,7 @@ func ApplyTransaction(config *chain.Config, blockHashFunc func(n uint64) libcomm
// about the transaction and calling mechanisms.
cfg.SkipAnalysis = SkipAnalysis(config, header.Number.Uint64())
- blockContext := NewEVMBlockContext(header, blockHashFunc, engine, author)
+ blockContext := NewEVMBlockContext(header, blockHashFunc, engine, author, config)
vmenv := vm.NewEVM(blockContext, evmtypes.TxContext{}, ibs, config, cfg)
return applyTransaction(config, engine, gp, ibs, stateWriter, header, tx, usedGas, usedBlobGas, vmenv, cfg)
diff --git a/core/state_transition.go b/core/state_transition.go
index 85ae1e53980..112229db8ec 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -32,7 +32,6 @@ import (
cmath "github.com/erigontech/erigon/common/math"
"github.com/erigontech/erigon/common/u256"
- "github.com/erigontech/erigon/consensus/misc"
"github.com/erigontech/erigon/core/types"
"github.com/erigontech/erigon/core/vm"
"github.com/erigontech/erigon/core/vm/evmtypes"
@@ -172,13 +171,10 @@ func (st *StateTransition) buyGas(gasBailout bool) error {
// compute blob fee for eip-4844 data blobs if any
blobGasVal := new(uint256.Int)
if st.evm.ChainRules().IsCancun {
- if st.evm.Context.ExcessBlobGas == nil {
+ blobGasPrice := st.evm.Context.BlobBaseFee
+ if blobGasPrice == nil {
return fmt.Errorf("%w: Cancun is active but ExcessBlobGas is nil", ErrInternalFailure)
}
- blobGasPrice, err := misc.GetBlobGasPrice(st.evm.ChainConfig(), *st.evm.Context.ExcessBlobGas)
- if err != nil {
- return err
- }
blobGasVal, overflow = blobGasVal.MulOverflow(blobGasPrice, new(uint256.Int).SetUint64(st.msg.BlobGas()))
if overflow {
return fmt.Errorf("%w: overflow converting blob gas: %v", ErrInsufficientFunds, blobGasVal)
@@ -211,7 +207,8 @@ func (st *StateTransition) buyGas(gasBailout bool) error {
}
}
}
- if have, want := st.state.GetBalance(st.msg.From()), balanceCheck; have.Cmp(want) < 0 {
+ balance := st.state.GetBalance(st.msg.From())
+ if have, want := balance, balanceCheck; have.Cmp(want) < 0 {
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From().Hex(), have, want)
}
st.state.SubBalance(st.msg.From(), gasVal)
@@ -280,18 +277,14 @@ func (st *StateTransition) preCheck(gasBailout bool) error {
}
}
if st.msg.BlobGas() > 0 && st.evm.ChainRules().IsCancun {
- if st.evm.Context.ExcessBlobGas == nil {
+ blobGasPrice := st.evm.Context.BlobBaseFee
+ if blobGasPrice == nil {
return fmt.Errorf("%w: Cancun is active but ExcessBlobGas is nil", ErrInternalFailure)
}
- blobGasPrice, err := misc.GetBlobGasPrice(st.evm.ChainConfig(), *st.evm.Context.ExcessBlobGas)
- if err != nil {
- return err
- }
maxFeePerBlobGas := st.msg.MaxFeePerBlobGas()
if !st.evm.Config().NoBaseFee && blobGasPrice.Cmp(maxFeePerBlobGas) > 0 {
- return fmt.Errorf("%w: address %v, maxFeePerBlobGas: %v blobGasPrice: %v, excessBlobGas: %v",
- ErrMaxFeePerBlobGas,
- st.msg.From().Hex(), st.msg.MaxFeePerBlobGas(), blobGasPrice, st.evm.Context.ExcessBlobGas)
+ return fmt.Errorf("%w: address %v, maxFeePerBlobGas: %v < blobGasPrice: %v",
+ ErrMaxFeePerBlobGas, st.msg.From().Hex(), st.msg.MaxFeePerBlobGas(), blobGasPrice)
}
}
diff --git a/core/vm/eips.go b/core/vm/eips.go
index 0a84338aaa3..df16397d83c 100644
--- a/core/vm/eips.go
+++ b/core/vm/eips.go
@@ -24,7 +24,6 @@ import (
libcommon "github.com/erigontech/erigon-lib/common"
- "github.com/erigontech/erigon/consensus/misc"
"github.com/erigontech/erigon/params"
)
@@ -303,11 +302,7 @@ func enable6780(jt *JumpTable) {
// opBlobBaseFee implements the BLOBBASEFEE opcode
func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) {
- excessBlobGas := interpreter.evm.Context.ExcessBlobGas
- blobBaseFee, err := misc.GetBlobGasPrice(interpreter.evm.ChainConfig(), *excessBlobGas)
- if err != nil {
- return nil, err
- }
+ blobBaseFee := interpreter.evm.Context.BlobBaseFee
callContext.Stack.Push(blobBaseFee)
return nil, nil
}
diff --git a/core/vm/evmtypes/evmtypes.go b/core/vm/evmtypes/evmtypes.go
index 121f08d8312..0c683c26e91 100644
--- a/core/vm/evmtypes/evmtypes.go
+++ b/core/vm/evmtypes/evmtypes.go
@@ -1,3 +1,19 @@
+// Copyright 2024 The Erigon Authors
+// This file is part of Erigon.
+//
+// Erigon 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.
+//
+// Erigon 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 Erigon. If not, see .
+
package evmtypes
import (
@@ -25,15 +41,15 @@ type BlockContext struct {
PostApplyMessage PostApplyMessageFunc
// Block information
- Coinbase common.Address // Provides information for COINBASE
- GasLimit uint64 // Provides information for GASLIMIT
- MaxGasLimit bool // Use GasLimit override for 2^256-1 (to be compatible with OpenEthereum's trace_call)
- BlockNumber uint64 // Provides information for NUMBER
- Time uint64 // Provides information for TIME
- Difficulty *big.Int // Provides information for DIFFICULTY
- BaseFee *uint256.Int // Provides information for BASEFEE
- PrevRanDao *common.Hash // Provides information for PREVRANDAO
- ExcessBlobGas *uint64 // Provides information for handling data blobs
+ Coinbase common.Address // Provides information for COINBASE
+ GasLimit uint64 // Provides information for GASLIMIT
+ MaxGasLimit bool // Use GasLimit override for 2^256-1 (to be compatible with OpenEthereum's trace_call)
+ BlockNumber uint64 // Provides information for NUMBER
+ Time uint64 // Provides information for TIME
+ Difficulty *big.Int // Provides information for DIFFICULTY
+ BaseFee *uint256.Int // Provides information for BASEFEE
+ PrevRanDao *common.Hash // Provides information for PREVRANDAO
+ BlobBaseFee *uint256.Int // Provides information for BLOBBASEFEE
}
// TxContext provides the EVM with information about a transaction.
diff --git a/erigon-lib/chain/chain_config.go b/erigon-lib/chain/chain_config.go
index 7dc9bd7a914..da32e2aa38f 100644
--- a/erigon-lib/chain/chain_config.go
+++ b/erigon-lib/chain/chain_config.go
@@ -75,6 +75,11 @@ type Config struct {
TargetBlobGasPerBlock *uint64 `json:"targetBlobGasPerBlock,omitempty"`
BlobGasPriceUpdateFraction *uint64 `json:"blobGasPriceUpdateFraction,omitempty"`
+ // EIP-7691
+ MaxBlobGasPerBlockPrague *uint64 `json:"maxBlobGasPerBlockPrague,omitempty"`
+ TargetBlobGasPerBlockPrague *uint64 `json:"targetBlobGasPerBlockPrague,omitempty"`
+ BlobGasPriceUpdateFractionPrague *uint64 `json:"blobGasPriceUpdateFractionPrague,omitempty"`
+
// (Optional) governance contract where EIP-1559 fees will be sent to, which otherwise would be burnt since the London fork.
// A key corresponds to the block number, starting from which the fees are sent to the address (map value).
// Starting from Prague, EIP-4844 fees might be collected as well:
@@ -261,29 +266,51 @@ func (c *Config) GetMinBlobGasPrice() uint64 {
return 1 // MIN_BLOB_GASPRICE (EIP-4844)
}
-func (c *Config) GetMaxBlobGasPerBlock() uint64 {
- if c != nil && c.MaxBlobGasPerBlock != nil {
- return *c.MaxBlobGasPerBlock
+func (c *Config) GetMaxBlobGasPerBlock(t uint64) uint64 {
+ if c != nil {
+ if c.IsPrague(t) {
+ if c.MaxBlobGasPerBlockPrague != nil {
+ return *c.MaxBlobGasPerBlockPrague
+ }
+ return 1179648 // EIP-7691
+ } else if c.MaxBlobGasPerBlock != nil {
+ return *c.MaxBlobGasPerBlock
+ }
}
return 786432 // MAX_BLOB_GAS_PER_BLOCK (EIP-4844)
}
-func (c *Config) GetTargetBlobGasPerBlock() uint64 {
- if c != nil && c.TargetBlobGasPerBlock != nil {
- return *c.TargetBlobGasPerBlock
+func (c *Config) GetTargetBlobGasPerBlock(t uint64) uint64 {
+ if c != nil {
+ if c.IsPrague(t) {
+ if c.TargetBlobGasPerBlockPrague != nil {
+ return *c.TargetBlobGasPerBlockPrague
+ }
+ return 786432
+ } else if c.TargetBlobGasPerBlock != nil {
+ return *c.TargetBlobGasPerBlock
+ }
}
return 393216 // TARGET_BLOB_GAS_PER_BLOCK (EIP-4844)
}
-func (c *Config) GetBlobGasPriceUpdateFraction() uint64 {
- if c != nil && c.BlobGasPriceUpdateFraction != nil {
- return *c.BlobGasPriceUpdateFraction
+func (c *Config) GetBlobGasPriceUpdateFraction(t uint64) uint64 {
+ if c != nil {
+ if c.IsPrague(t) {
+ if c.BlobGasPriceUpdateFractionPrague != nil {
+ return *c.BlobGasPriceUpdateFractionPrague
+ }
+ return 5007716
+
+ } else if c.BlobGasPriceUpdateFraction != nil {
+ return *c.BlobGasPriceUpdateFraction
+ }
}
return 3338477 // BLOB_GASPRICE_UPDATE_FRACTION (EIP-4844)
}
-func (c *Config) GetMaxBlobsPerBlock() uint64 {
- return c.GetMaxBlobGasPerBlock() / fixedgas.BlobGasPerBlob
+func (c *Config) GetMaxBlobsPerBlock(time uint64) uint64 {
+ return c.GetMaxBlobGasPerBlock(time) / fixedgas.BlobGasPerBlob
}
// CheckCompatible checks whether scheduled fork transitions have been imported
diff --git a/erigon-lib/txpool/pool.go b/erigon-lib/txpool/pool.go
index 065915c1624..a3bb37825ad 100644
--- a/erigon-lib/txpool/pool.go
+++ b/erigon-lib/txpool/pool.go
@@ -233,6 +233,7 @@ type TxPool struct {
pragueTime *uint64
isPostPrague atomic.Bool
maxBlobsPerBlock uint64
+ maxBlobsPerBlockPrague *uint64
feeCalculator FeeCalculator
logger log.Logger
}
@@ -243,6 +244,7 @@ type FeeCalculator interface {
func New(newTxs chan types.Announcements, coreDB kv.RoDB, cfg txpoolcfg.Config, cache kvcache.Cache,
chainID uint256.Int, shanghaiTime, agraBlock, cancunTime, pragueTime *big.Int, maxBlobsPerBlock uint64,
+ maxBlobsPerBlockPrague *uint64,
feeCalculator FeeCalculator, logger log.Logger,
) (*TxPool, error) {
localsHistory, err := simplelru.NewLRU[string, struct{}](10_000, nil)
@@ -289,8 +291,11 @@ func New(newTxs chan types.Announcements, coreDB kv.RoDB, cfg txpoolcfg.Config,
minedBlobTxsByBlock: map[uint64][]*metaTx{},
minedBlobTxsByHash: map[string]*metaTx{},
maxBlobsPerBlock: maxBlobsPerBlock,
+ maxBlobsPerBlockPrague: maxBlobsPerBlockPrague,
feeCalculator: feeCalculator,
- logger: logger,
+ // builderNotifyNewTxns: builderNotifyNewTxns,
+ // newSlotsStreams: newSlotsStreams,
+ logger: logger,
}
if shanghaiTime != nil {
@@ -864,7 +869,7 @@ func (p *TxPool) validateTx(txn *types.TxSlot, isLocal bool, stateCache kvcache.
if blobCount == 0 {
return txpoolcfg.NoBlobs
}
- if blobCount > p.maxBlobsPerBlock {
+ if blobCount > p.GetMaxBlobsPerBlock() {
return txpoolcfg.TooManyBlobs
}
equalNumber := len(txn.BlobHashes) == len(txn.Blobs) &&
@@ -1073,6 +1078,17 @@ func (p *TxPool) isPrague() bool {
return isTimeBasedForkActivated(&p.isPostPrague, p.pragueTime)
}
+func (p *TxPool) GetMaxBlobsPerBlock() uint64 {
+ if p.isPrague() {
+ if p.maxBlobsPerBlockPrague != nil {
+ return *p.maxBlobsPerBlockPrague
+ }
+ return 9 // EIP-7691 default
+ } else {
+ return p.maxBlobsPerBlock
+ }
+}
+
// Check that the serialized txn should not exceed a certain max size
func (p *TxPool) ValidateSerializedTxn(serializedTxn []byte) error {
const (
diff --git a/erigon-lib/txpool/pool_fuzz_test.go b/erigon-lib/txpool/pool_fuzz_test.go
index a4b00577406..0e6c826c1db 100644
--- a/erigon-lib/txpool/pool_fuzz_test.go
+++ b/erigon-lib/txpool/pool_fuzz_test.go
@@ -314,7 +314,7 @@ func FuzzOnNewBlocks(f *testing.F) {
cfg := txpoolcfg.DefaultConfig
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
- pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
+ pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, nil, log.New())
assert.NoError(err)
err = pool.Start(ctx, db)
@@ -540,7 +540,7 @@ func FuzzOnNewBlocks(f *testing.F) {
check(p2pReceived, types.TxSlots{}, "after_flush")
checkNotify(p2pReceived, types.TxSlots{}, "after_flush")
- p2, err := New(ch, coreDB, txpoolcfg.DefaultConfig, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
+ p2, err := New(ch, coreDB, txpoolcfg.DefaultConfig, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, nil, log.New())
assert.NoError(err)
p2.senders = pool.senders // senders are not persisted
diff --git a/erigon-lib/txpool/pool_test.go b/erigon-lib/txpool/pool_test.go
index 70b707b52f3..88ce27218f2 100644
--- a/erigon-lib/txpool/pool_test.go
+++ b/erigon-lib/txpool/pool_test.go
@@ -53,7 +53,7 @@ func TestNonceFromAddress(t *testing.T) {
cfg := txpoolcfg.DefaultConfig
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
- pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
+ pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, nil, log.New())
assert.NoError(err)
require.True(pool != nil)
ctx := context.Background()
@@ -173,7 +173,7 @@ func TestReplaceWithHigherFee(t *testing.T) {
cfg := txpoolcfg.DefaultConfig
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
- pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
+ pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, nil, log.New())
assert.NoError(err)
require.NotEqual(nil, pool)
ctx := context.Background()
@@ -290,7 +290,7 @@ func TestReverseNonces(t *testing.T) {
cfg := txpoolcfg.DefaultConfig
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
- pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
+ pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, nil, log.New())
assert.NoError(err)
require.True(pool != nil)
ctx := context.Background()
@@ -417,7 +417,7 @@ func TestTxPoke(t *testing.T) {
cfg := txpoolcfg.DefaultConfig
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
- pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
+ pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, nil, log.New())
assert.NoError(err)
require.True(pool != nil)
ctx := context.Background()
@@ -706,7 +706,7 @@ func TestShanghaiValidateTx(t *testing.T) {
}
cache := &kvcache.DummyCache{}
- pool, err := New(ch, coreDB, cfg, cache, *u256.N1, shanghaiTime, nil /* agraBlock */, nil /* cancunTime */, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, logger)
+ pool, err := New(ch, coreDB, cfg, cache, *u256.N1, shanghaiTime, nil /* agraBlock */, nil /* cancunTime */, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, nil, logger)
asrt.NoError(err)
ctx := context.Background()
tx, err := coreDB.BeginRw(ctx)
@@ -755,7 +755,7 @@ func TestSetCodeTxValidationWithLargeAuthorizationValues(t *testing.T) {
cache := &kvcache.DummyCache{}
logger := log.New()
pool, err := New(ch, coreDB, cfg, cache, chainID, common.Big0 /* shanghaiTime */, nil, /* agraBlock */
- common.Big0 /* cancunTime */, common.Big0 /* pragueTime */, fixedgas.DefaultMaxBlobsPerBlock, nil, logger)
+ common.Big0 /* cancunTime */, common.Big0 /* pragueTime */, fixedgas.DefaultMaxBlobsPerBlock, nil, nil, logger)
assert.NoError(t, err)
ctx := context.Background()
tx, err := coreDB.BeginRw(ctx)
@@ -800,7 +800,7 @@ func TestBlobTxReplacement(t *testing.T) {
db, coreDB := memdb.NewTestPoolDB(t), memdb.NewTestDB(t)
cfg := txpoolcfg.DefaultConfig
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
- pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, common.Big0, nil, common.Big0, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
+ pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, common.Big0, nil, common.Big0, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, nil, log.New())
assert.NoError(err)
require.True(pool != nil)
ctx := context.Background()
@@ -1017,7 +1017,7 @@ func TestDropRemoteAtNoGossip(t *testing.T) {
logger := log.New()
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
- txPool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, big.NewInt(0), big.NewInt(0), nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, logger)
+ txPool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, big.NewInt(0), big.NewInt(0), nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, nil, logger)
assert.NoError(err)
require.True(txPool != nil)
@@ -1123,7 +1123,7 @@ func TestBlobSlots(t *testing.T) {
cfg.TotalBlobPoolLimit = 20
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
- pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, common.Big0, nil, common.Big0, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
+ pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, common.Big0, nil, common.Big0, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, nil, log.New())
assert.NoError(err)
require.True(pool != nil)
ctx := context.Background()
@@ -1197,7 +1197,7 @@ func TestGasLimitChanged(t *testing.T) {
cfg := txpoolcfg.DefaultConfig
sendersCache := kvcache.New(kvcache.DefaultCoherentConfig)
- pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New())
+ pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, nil, log.New())
assert.NoError(err)
require.True(pool != nil)
ctx := context.Background()
diff --git a/erigon-lib/txpool/txpoolutil/all_components.go b/erigon-lib/txpool/txpoolutil/all_components.go
index f009b5876e0..84618e0f385 100644
--- a/erigon-lib/txpool/txpoolutil/all_components.go
+++ b/erigon-lib/txpool/txpoolutil/all_components.go
@@ -132,7 +132,7 @@ func AllComponents(ctx context.Context, cfg txpoolcfg.Config, cache kvcache.Cach
}
chainID, _ := uint256.FromBig(chainConfig.ChainID)
- maxBlobsPerBlock := chainConfig.GetMaxBlobsPerBlock()
+ maxBlobsPerBlock := chainConfig.GetMaxBlobsPerBlock(uint64(time.Now().Second()))
shanghaiTime := chainConfig.ShanghaiTime
var agraBlock *big.Int
@@ -146,7 +146,7 @@ func AllComponents(ctx context.Context, cfg txpoolcfg.Config, cache kvcache.Cach
}
txPool, err := txpool.New(newTxs, chainDB, cfg, cache, *chainID, shanghaiTime, agraBlock, cancunTime, pragueTime,
- maxBlobsPerBlock, feeCalculator, logger)
+ maxBlobsPerBlock, &maxBlobsPerBlock, feeCalculator, logger)
if err != nil {
return nil, nil, nil, nil, nil, err
}
diff --git a/eth/ethutils/receipt.go b/eth/ethutils/receipt.go
index 8e0725788d4..62825e02ec0 100644
--- a/eth/ethutils/receipt.go
+++ b/eth/ethutils/receipt.go
@@ -77,7 +77,7 @@ func MarshalReceipt(
if header.ExcessBlobGas == nil {
log.Warn("excess blob gas not set when trying to marshal blob tx")
} else {
- blobGasPrice, err := misc.GetBlobGasPrice(chainConfig, *header.ExcessBlobGas)
+ blobGasPrice, err := misc.GetBlobGasPrice(chainConfig, *header.ExcessBlobGas, header.Time)
if err != nil {
log.Error(err.Error())
}
diff --git a/eth/gasprice/feehistory.go b/eth/gasprice/feehistory.go
index 38736be31cb..99bc2faa6c5 100644
--- a/eth/gasprice/feehistory.go
+++ b/eth/gasprice/feehistory.go
@@ -51,10 +51,13 @@ type blockFees struct {
block *types.Block // only set if reward percentiles are requested
receipts types.Receipts
// filled by processBlock
- reward []*big.Int
- baseFee, nextBaseFee *big.Int
- gasUsedRatio float64
- err error
+ reward []*big.Int
+ baseFee, nextBaseFee *big.Int
+ blobBaseFee, nextBlobBaseFee *big.Int
+ gasUsedRatio float64
+ blobGasUsedRatio float64
+ secondsPerSlot uint64
+ err error
}
// txGasAndReward is sorted in ascending order based on reward
@@ -87,7 +90,32 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
} else {
bf.nextBaseFee = new(big.Int)
}
+
+ // Fill in blob base fee and next blob base fee.
+ if excessBlobGas := bf.header.ExcessBlobGas; excessBlobGas != nil {
+ blobBaseFee256, err := misc.GetBlobGasPrice(chainconfig, *excessBlobGas, bf.header.Time)
+ if err != nil {
+ bf.err = err
+ return
+ }
+ nextBlobBaseFee256, err := misc.GetBlobGasPrice(chainconfig, misc.CalcExcessBlobGas(chainconfig, bf.header, bf.header.Time+bf.secondsPerSlot), bf.header.Time+bf.secondsPerSlot)
+ if err != nil {
+ bf.err = err
+ return
+ }
+ bf.blobBaseFee = blobBaseFee256.ToBig()
+ bf.nextBlobBaseFee = nextBlobBaseFee256.ToBig()
+
+ } else {
+ bf.blobBaseFee = new(big.Int)
+ bf.nextBlobBaseFee = new(big.Int)
+ }
bf.gasUsedRatio = float64(bf.header.GasUsed) / float64(bf.header.GasLimit)
+
+ if blobGasUsed := bf.header.BlobGasUsed; blobGasUsed != nil && chainconfig.GetMaxBlobGasPerBlock(bf.header.Time) != 0 {
+ bf.blobGasUsedRatio = float64(*blobGasUsed) / float64(chainconfig.GetMaxBlobGasPerBlock(bf.header.Time))
+ }
+
if len(percentiles) == 0 {
// rewards were not requested, return null
return
@@ -135,23 +163,26 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
// also returned if requested and available.
// Note: an error is only returned if retrieving the head header has failed. If there are no
// retrievable blocks in the specified range then zero block count is returned with no error.
-func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.BlockNumber, blocks, maxHistory int) (*types.Block, []*types.Receipt, uint64, int, error) {
+func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.BlockNumber, blocks, maxHistory int) (*types.Block, []*types.Receipt, uint64, int, uint64, error) {
var (
headBlock rpc.BlockNumber
pendingBlock *types.Block
pendingReceipts types.Receipts
+ secondsPerSlot uint64 // Time diff from parent block as an approx
+ lastBlockTime uint64
)
// query either pending block or head header and set headBlock
if lastBlock == rpc.PendingBlockNumber {
if pendingBlock, pendingReceipts = oracle.backend.PendingBlockAndReceipts(); pendingBlock != nil {
lastBlock = rpc.BlockNumber(pendingBlock.NumberU64())
headBlock = lastBlock - 1
+ lastBlockTime = pendingBlock.Time()
} else {
// pending block not supported by backend, process until latest block
lastBlock = rpc.LatestBlockNumber
blocks--
if blocks == 0 {
- return nil, nil, 0, 0, nil
+ return nil, nil, 0, 0, 0, nil
}
}
}
@@ -159,14 +190,24 @@ func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.Block
// if pending block is not fetched then we retrieve the head header to get the head block number
if latestHeader, err := oracle.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber); err == nil {
headBlock = rpc.BlockNumber(latestHeader.Number.Uint64())
+ lastBlockTime = latestHeader.Time
} else {
- return nil, nil, 0, 0, err
+ return nil, nil, 0, 0, 0, err
}
}
if lastBlock == rpc.LatestBlockNumber {
lastBlock = headBlock
} else if pendingBlock == nil && lastBlock > headBlock {
- return nil, nil, 0, 0, fmt.Errorf("%w: requested %d, head %d", ErrRequestBeyondHead, lastBlock, headBlock)
+ return nil, nil, 0, 0, 0, fmt.Errorf("%w: requested %d, head %d", ErrRequestBeyondHead, lastBlock, headBlock)
+ }
+ if lastBlock > 0 {
+ parentHeader, err := oracle.backend.HeaderByNumber(ctx, lastBlock-1)
+ if err != nil {
+ return nil, nil, 0, 0, 0, err
+ }
+ if parentHeader != nil {
+ secondsPerSlot = parentHeader.Time - lastBlockTime
+ }
}
if maxHistory != 0 {
// limit retrieval to the given number of latest blocks
@@ -175,7 +216,7 @@ func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.Block
if int64(blocks) > tooOldCount {
blocks -= int(tooOldCount)
} else {
- return nil, nil, 0, 0, nil
+ return nil, nil, 0, 0, 0, nil
}
}
}
@@ -183,7 +224,7 @@ func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.Block
if rpc.BlockNumber(blocks) > lastBlock+1 {
blocks = int(lastBlock + 1)
}
- return pendingBlock, pendingReceipts, uint64(lastBlock), blocks, nil
+ return pendingBlock, pendingReceipts, uint64(lastBlock), blocks, secondsPerSlot, nil
}
// FeeHistory returns data relevant for fee estimation based on the specified range of blocks.
@@ -226,7 +267,7 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLast
pendingReceipts []*types.Receipt
err error
)
- pendingBlock, pendingReceipts, lastBlock, blocks, err := oracle.resolveBlockRange(ctx, unresolvedLastBlock, blocks, maxHistory)
+ pendingBlock, pendingReceipts, lastBlock, blocks, secondsPerSlot, err := oracle.resolveBlockRange(ctx, unresolvedLastBlock, blocks, maxHistory)
if err != nil || blocks == 0 {
return libcommon.Big0, nil, nil, nil, err
}
@@ -251,7 +292,7 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLast
continue
}
- fees := &blockFees{blockNumber: blockNumber}
+ fees := &blockFees{blockNumber: blockNumber, secondsPerSlot: secondsPerSlot}
if pendingBlock != nil && blockNumber >= pendingBlock.NumberU64() {
fees.block, fees.receipts = pendingBlock, pendingReceipts
} else {
diff --git a/eth/stagedsync/exec3.go b/eth/stagedsync/exec3.go
index c36ccbc463d..e8891ec7ca9 100644
--- a/eth/stagedsync/exec3.go
+++ b/eth/stagedsync/exec3.go
@@ -532,7 +532,7 @@ Loop:
defer getHashFnMute.Unlock()
return f(n)
}
- blockContext := core.NewEVMBlockContext(header, getHashFn, engine, nil /* author */)
+ blockContext := core.NewEVMBlockContext(header, getHashFn, engine, nil /* author */, chainConfig)
if parallel {
select {
@@ -1059,7 +1059,7 @@ func reconstituteStep(last bool,
defer getHashFnMute.Unlock()
return f(n)
}
- blockContext := core.NewEVMBlockContext(header, getHashFn, engine, nil /* author */)
+ blockContext := core.NewEVMBlockContext(header, getHashFn, engine, nil /* author */, chainConfig)
rules := chainConfig.Rules(bn, b.Time())
for txIndex := -1; txIndex <= len(txs); txIndex++ {
diff --git a/eth/stagedsync/stage_mining_exec.go b/eth/stagedsync/stage_mining_exec.go
index a04d9e88e1e..164cb6363bc 100644
--- a/eth/stagedsync/stage_mining_exec.go
+++ b/eth/stagedsync/stage_mining_exec.go
@@ -197,7 +197,7 @@ func getNextTransactions(
remainingGas := header.GasLimit - header.GasUsed
remainingBlobGas := uint64(0)
if header.BlobGasUsed != nil {
- remainingBlobGas = cfg.chainConfig.GetMaxBlobGasPerBlock() - *header.BlobGasUsed
+ remainingBlobGas = cfg.chainConfig.GetMaxBlobGasPerBlock(header.Time) - *header.BlobGasUsed
}
if _, count, err = cfg.txPool.YieldBest(amount, &txSlots, poolTx, executionAt, remainingGas, remainingBlobGas, alreadyYielded); err != nil {
@@ -377,7 +377,7 @@ func addTransactionsToMiningBlock(logPrefix string, current *MiningBlock, chainC
tcount := 0
gasPool := new(core.GasPool).AddGas(header.GasLimit - header.GasUsed)
if header.BlobGasUsed != nil {
- gasPool.AddBlobGas(chainConfig.GetMaxBlobGasPerBlock() - *header.BlobGasUsed)
+ gasPool.AddBlobGas(chainConfig.GetMaxBlobGasPerBlock(header.Time) - *header.BlobGasUsed)
}
signer := types.MakeSigner(&chainConfig, header.Number.Uint64(), header.Time)
diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go
index f930bca90c8..ece271bdb53 100644
--- a/eth/tracers/tracers_test.go
+++ b/eth/tracers/tracers_test.go
@@ -1,18 +1,21 @@
// Copyright 2017 The go-ethereum Authors
-// This file is part of the go-ethereum library.
+// (original work)
+// Copyright 2025 The Erigon Authors
+// (modifications)
+// This file is part of Erigon.
//
-// The go-ethereum library is free software: you can redistribute it and/or modify
+// Erigon 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,
+// Erigon 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 .
+// along with Erigon. If not, see .
package tracers_test
@@ -72,18 +75,17 @@ func TestPrestateTracerCreate2(t *testing.T) {
Origin: origin,
GasPrice: uint256.NewInt(1),
}
- excessBlobGas := uint64(50000)
context := evmtypes.BlockContext{
- CanTransfer: core.CanTransfer,
- Transfer: consensus.Transfer,
- Coinbase: libcommon.Address{},
- BlockNumber: 8000000,
- Time: 5,
- Difficulty: big.NewInt(0x30000),
- GasLimit: uint64(6000000),
- ExcessBlobGas: &excessBlobGas,
+ CanTransfer: core.CanTransfer,
+ Transfer: consensus.Transfer,
+ Coinbase: libcommon.Address{},
+ BlockNumber: 8000000,
+ Time: 5,
+ Difficulty: big.NewInt(0x30000),
+ GasLimit: uint64(6000000),
+ BaseFee: uint256.NewInt(0),
+ BlobBaseFee: uint256.NewInt(50000),
}
- context.BaseFee = uint256.NewInt(0)
alloc := types.GenesisAlloc{}
// The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns
diff --git a/tests/state_test_util.go b/tests/state_test_util.go
index ed132b2dfb4..41d2f0d9f8f 100644
--- a/tests/state_test_util.go
+++ b/tests/state_test_util.go
@@ -235,7 +235,7 @@ func (t *StateTest) RunNoVerify(tx kv.RwTx, subtest StateSubtest, vmconfig vm.Co
// Prepare the EVM.
txContext := core.NewEVMTxContext(msg)
header := block.Header()
- context := core.NewEVMBlockContext(header, core.GetHashFn(header, nil), nil, &t.json.Env.Coinbase)
+ context := core.NewEVMBlockContext(header, core.GetHashFn(header, nil), nil, &t.json.Env.Coinbase, config)
context.GetHash = vmTestBlockHash
if baseFee != nil {
context.BaseFee = new(uint256.Int)
@@ -244,13 +244,14 @@ func (t *StateTest) RunNoVerify(tx kv.RwTx, subtest StateSubtest, vmconfig vm.Co
if t.json.Env.Random != nil {
rnd := libcommon.BigToHash(t.json.Env.Random)
context.PrevRanDao = &rnd
+ context.Difficulty = big.NewInt(0)
}
evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
// Execute the message.
snapshot := statedb.Snapshot()
gaspool := new(core.GasPool)
- gaspool.AddGas(block.GasLimit()).AddBlobGas(config.GetMaxBlobGasPerBlock())
+ gaspool.AddGas(block.GasLimit()).AddBlobGas(config.GetMaxBlobGasPerBlock(header.Time))
if _, err = core.ApplyMessage(evm, msg, gaspool, true /* refunds */, false /* gasBailout */); err != nil {
statedb.RevertToSnapshot(snapshot)
}
diff --git a/turbo/engineapi/engine_server.go b/turbo/engineapi/engine_server.go
index eff517858d1..dcd4bc38e57 100644
--- a/turbo/engineapi/engine_server.go
+++ b/turbo/engineapi/engine_server.go
@@ -242,7 +242,7 @@ func (s *EngineServer) newPayload(ctx context.Context, req *engine_types.Executi
}
if version >= clparams.DenebVersion {
- err := ethutils.ValidateBlobs(req.BlobGasUsed.Uint64(), s.config.GetMaxBlobGasPerBlock(), s.config.GetMaxBlobsPerBlock(), expectedBlobHashes, &transactions)
+ err := ethutils.ValidateBlobs(req.BlobGasUsed.Uint64(), s.config.GetMaxBlobGasPerBlock(header.Time), s.config.GetMaxBlobsPerBlock(header.Time), expectedBlobHashes, &transactions)
if errors.Is(err, ethutils.ErrNilBlobHashes) {
return nil, &rpc.InvalidParamsError{Message: "nil blob hashes array"}
}
diff --git a/turbo/execution/eth1/inserters.go b/turbo/execution/eth1/inserters.go
index d0751720220..1e1bfdf23cd 100644
--- a/turbo/execution/eth1/inserters.go
+++ b/turbo/execution/eth1/inserters.go
@@ -3,36 +3,14 @@ package eth1
import (
"context"
"fmt"
- "reflect"
- libcommon "github.com/erigontech/erigon-lib/common"
"github.com/erigontech/erigon-lib/common/metrics"
"github.com/erigontech/erigon-lib/gointerfaces/execution"
"github.com/erigontech/erigon/core/rawdb"
- "github.com/erigontech/erigon/core/types"
- "github.com/erigontech/erigon/rpc"
+
"github.com/erigontech/erigon/turbo/execution/eth1/eth1_utils"
)
-func (s *EthereumExecutionModule) validatePayloadBlobs(expectedBlobHashes []libcommon.Hash, transactions []types.Transaction, blobGasUsed uint64) error {
- if expectedBlobHashes == nil {
- return &rpc.InvalidParamsError{Message: "nil blob hashes array"}
- }
- actualBlobHashes := []libcommon.Hash{}
- for _, txn := range transactions {
- actualBlobHashes = append(actualBlobHashes, txn.GetBlobHashes()...)
- }
- if len(actualBlobHashes) > int(s.config.GetMaxBlobsPerBlock()) || blobGasUsed > s.config.GetMaxBlobGasPerBlock() {
- return nil
- }
- if !reflect.DeepEqual(actualBlobHashes, expectedBlobHashes) {
- s.logger.Warn("[NewPayload] mismatch in blob hashes",
- "expectedBlobHashes", expectedBlobHashes, "actualBlobHashes", actualBlobHashes)
- return nil
- }
- return nil
-}
-
func (e *EthereumExecutionModule) InsertBlocks(ctx context.Context, req *execution.InsertBlocksRequest) (*execution.InsertionResult, error) {
if !e.semaphore.TryAcquire(1) {
e.logger.Trace("ethereumExecutionModule.InsertBlocks: ExecutionStatus_Busy")
diff --git a/turbo/jsonrpc/eth_block.go b/turbo/jsonrpc/eth_block.go
index 9e3e6155f29..ba94c7104f8 100644
--- a/turbo/jsonrpc/eth_block.go
+++ b/turbo/jsonrpc/eth_block.go
@@ -122,7 +122,7 @@ func (api *APIImpl) CallBundle(ctx context.Context, txHashes []common.Hash, stat
return nil, err
}
- blockCtx := transactions.NewEVMBlockContext(engine, header, stateBlockNumberOrHash.RequireCanonical, tx, api._blockReader)
+ blockCtx := transactions.NewEVMBlockContext(engine, header, stateBlockNumberOrHash.RequireCanonical, tx, api._blockReader, chainConfig)
txCtx := core.NewEVMTxContext(firstMsg)
// Get a new instance of the EVM
evm := vm.NewEVM(blockCtx, txCtx, ibs, chainConfig, vm.Config{Debug: false})
diff --git a/turbo/jsonrpc/eth_call.go b/turbo/jsonrpc/eth_call.go
index 70519119ee8..fdb1074ce30 100644
--- a/turbo/jsonrpc/eth_call.go
+++ b/turbo/jsonrpc/eth_call.go
@@ -549,7 +549,7 @@ func (api *APIImpl) CreateAccessList(ctx context.Context, args ethapi2.CallArgs,
// Apply the transaction with the access list tracer
tracer := logger.NewAccessListTracer(accessList, excl, state)
config := vm.Config{Tracer: tracer, Debug: true, NoBaseFee: true}
- blockCtx := transactions.NewEVMBlockContext(engine, header, bNrOrHash.RequireCanonical, tx, api._blockReader)
+ blockCtx := transactions.NewEVMBlockContext(engine, header, bNrOrHash.RequireCanonical, tx, api._blockReader, chainConfig)
txCtx := core.NewEVMTxContext(msg)
evm := vm.NewEVM(blockCtx, txCtx, state, chainConfig, config)
diff --git a/turbo/jsonrpc/eth_callMany.go b/turbo/jsonrpc/eth_callMany.go
index e2fc12af8b9..76f3d0cd75f 100644
--- a/turbo/jsonrpc/eth_callMany.go
+++ b/turbo/jsonrpc/eth_callMany.go
@@ -155,7 +155,7 @@ func (api *APIImpl) CallMany(ctx context.Context, bundles []Bundle, simulateCont
return hash
}
- blockCtx = core.NewEVMBlockContext(header, getHash, api.engine(), nil /* author */)
+ blockCtx = core.NewEVMBlockContext(header, getHash, api.engine(), nil /* author */, chainConfig)
// Get a new instance of the EVM
evm = vm.NewEVM(blockCtx, txCtx, st, chainConfig, vm.Config{Debug: false})
diff --git a/turbo/jsonrpc/eth_receipts.go b/turbo/jsonrpc/eth_receipts.go
index 75aae170cc8..45900794bf8 100644
--- a/turbo/jsonrpc/eth_receipts.go
+++ b/turbo/jsonrpc/eth_receipts.go
@@ -59,7 +59,7 @@ func (api *BaseAPI) getReceipts(ctx context.Context, tx kv.Tx, block *types.Bloc
usedGas := new(uint64)
usedBlobGas := new(uint64)
- gp := new(core.GasPool).AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock())
+ gp := new(core.GasPool).AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock(block.Time()))
noopWriter := state.NewNoopWriter()
@@ -528,7 +528,7 @@ func txnExecutor(tx kv.TemporalTx, chainConfig *chain.Config, engine consensus.E
func (e *intraBlockExec) changeBlock(header *types.Header) {
e.blockNum = header.Number.Uint64()
- blockCtx := transactions.NewEVMBlockContext(e.engine, header, true /* requireCanonical */, e.tx, e.br)
+ blockCtx := transactions.NewEVMBlockContext(e.engine, header, true /* requireCanonical */, e.tx, e.br, e.chainConfig)
e.blockCtx = &blockCtx
e.blockHash = header.Hash()
e.header = header
diff --git a/turbo/jsonrpc/eth_system.go b/turbo/jsonrpc/eth_system.go
index 2f333d4a1ca..06b1bb33b84 100644
--- a/turbo/jsonrpc/eth_system.go
+++ b/turbo/jsonrpc/eth_system.go
@@ -201,6 +201,7 @@ func (b *GasPriceOracleBackend) HeaderByNumber(ctx context.Context, number rpc.B
}
return header, nil
}
+
func (b *GasPriceOracleBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
return b.baseApi.blockByRPCNumber(ctx, number, b.tx)
}
diff --git a/turbo/jsonrpc/otterscan_generic_tracer.go b/turbo/jsonrpc/otterscan_generic_tracer.go
index cd3da0100dd..1dbf1d51f30 100644
--- a/turbo/jsonrpc/otterscan_generic_tracer.go
+++ b/turbo/jsonrpc/otterscan_generic_tracer.go
@@ -94,7 +94,7 @@ func (api *OtterscanAPIImpl) genericTracer(dbtx kv.Tx, ctx context.Context, bloc
msg, _ := tx.AsMessage(*signer, header.BaseFee, rules)
- BlockContext := core.NewEVMBlockContext(header, core.GetHashFn(header, getHeader), engine, nil)
+ BlockContext := core.NewEVMBlockContext(header, core.GetHashFn(header, getHeader), engine, nil, chainConfig)
TxContext := core.NewEVMTxContext(msg)
vmenv := vm.NewEVM(BlockContext, TxContext, ibs, chainConfig, vm.Config{Debug: true, Tracer: tracer})
diff --git a/turbo/jsonrpc/otterscan_search_trace.go b/turbo/jsonrpc/otterscan_search_trace.go
index 7a64301ae10..0e64201a2e1 100644
--- a/turbo/jsonrpc/otterscan_search_trace.go
+++ b/turbo/jsonrpc/otterscan_search_trace.go
@@ -94,7 +94,7 @@ func (api *OtterscanAPIImpl) traceBlock(dbtx kv.Tx, ctx context.Context, blockNu
msg, _ := tx.AsMessage(*signer, header.BaseFee, rules)
tracer := NewTouchTracer(searchAddr)
- BlockContext := core.NewEVMBlockContext(header, core.GetHashFn(header, getHeader), engine, nil)
+ BlockContext := core.NewEVMBlockContext(header, core.GetHashFn(header, getHeader), engine, nil, chainConfig)
TxContext := core.NewEVMTxContext(msg)
vmenv := vm.NewEVM(BlockContext, TxContext, ibs, chainConfig, vm.Config{Debug: true, Tracer: tracer})
diff --git a/turbo/jsonrpc/overlay_api.go b/turbo/jsonrpc/overlay_api.go
index ffbf16bdb82..fe2b0850cb7 100644
--- a/turbo/jsonrpc/overlay_api.go
+++ b/turbo/jsonrpc/overlay_api.go
@@ -414,7 +414,6 @@ func (api *OverlayAPIImpl) replayBlock(ctx context.Context, blockNum uint64, sta
blockCtx evmtypes.BlockContext
txCtx evmtypes.TxContext
overrideBlockHash map[uint64]common.Hash
- baseFee uint256.Int
)
blockLogs := []*types.Log{}
@@ -451,23 +450,7 @@ func (api *OverlayAPIImpl) replayBlock(ctx context.Context, blockNum uint64, sta
return hash
}
- if parent.BaseFee != nil {
- baseFee.SetFromBig(parent.BaseFee)
- }
-
- var excessBlobGas uint64 = 0
- blockCtx = evmtypes.BlockContext{
- CanTransfer: core.CanTransfer,
- Transfer: consensus.Transfer,
- GetHash: getHash,
- Coinbase: parent.Coinbase,
- BlockNumber: parent.Number.Uint64(),
- Time: parent.Time,
- Difficulty: new(big.Int).Set(parent.Difficulty),
- GasLimit: parent.GasLimit,
- BaseFee: &baseFee,
- ExcessBlobGas: &excessBlobGas,
- }
+ blockCtx = core.NewEVMBlockContext(parent, getHash, api.engine(), nil, chainConfig)
signer := types.MakeSigner(chainConfig, blockNum, blockCtx.Time)
rules := chainConfig.Rules(blockNum, blockCtx.Time)
diff --git a/turbo/jsonrpc/trace_adhoc.go b/turbo/jsonrpc/trace_adhoc.go
index 5df91faf428..7b2adc8e83f 100644
--- a/turbo/jsonrpc/trace_adhoc.go
+++ b/turbo/jsonrpc/trace_adhoc.go
@@ -1001,7 +1001,7 @@ func (api *TraceAPIImpl) Call(ctx context.Context, args TraceCallParam, traceTyp
return nil, err
}
- blockCtx := transactions.NewEVMBlockContext(engine, header, blockNrOrHash.RequireCanonical, tx, api._blockReader)
+ blockCtx := transactions.NewEVMBlockContext(engine, header, blockNrOrHash.RequireCanonical, tx, api._blockReader, chainConfig)
txCtx := core.NewEVMTxContext(msg)
blockCtx.GasLimit = math.MaxUint64
@@ -1239,7 +1239,7 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, stateReader
vmConfig.Tracer = &ot
}
- blockCtx := transactions.NewEVMBlockContext(engine, header, parentNrOrHash.RequireCanonical, dbtx, api._blockReader)
+ blockCtx := transactions.NewEVMBlockContext(engine, header, parentNrOrHash.RequireCanonical, dbtx, api._blockReader, chainConfig)
if useParent {
blockCtx.GasLimit = math.MaxUint64
blockCtx.MaxGasLimit = true
diff --git a/turbo/jsonrpc/trace_filtering.go b/turbo/jsonrpc/trace_filtering.go
index 1736b0c0a97..0fca43cabd4 100644
--- a/turbo/jsonrpc/trace_filtering.go
+++ b/turbo/jsonrpc/trace_filtering.go
@@ -788,7 +788,7 @@ func (api *TraceAPIImpl) filterV3(ctx context.Context, dbtx kv.TemporalTx, fromB
vmConfig.Tracer = &ot
ibs := state.New(cachedReader)
- blockCtx := transactions.NewEVMBlockContext(engine, lastHeader, true /* requireCanonical */, dbtx, api._blockReader)
+ blockCtx := transactions.NewEVMBlockContext(engine, lastHeader, true /* requireCanonical */, dbtx, api._blockReader, chainConfig)
txCtx := core.NewEVMTxContext(msg)
evm := vm.NewEVM(blockCtx, txCtx, ibs, chainConfig, vmConfig)
diff --git a/turbo/jsonrpc/tracing.go b/turbo/jsonrpc/tracing.go
index b5bcc4b7388..9d2dfcd5976 100644
--- a/turbo/jsonrpc/tracing.go
+++ b/turbo/jsonrpc/tracing.go
@@ -361,7 +361,7 @@ func (api *PrivateDebugAPIImpl) TraceCall(ctx context.Context, args ethapi.CallA
return fmt.Errorf("convert args to msg: %v", err)
}
- blockCtx := transactions.NewEVMBlockContext(engine, header, blockNrOrHash.RequireCanonical, dbtx, api._blockReader)
+ blockCtx := transactions.NewEVMBlockContext(engine, header, blockNrOrHash.RequireCanonical, dbtx, api._blockReader, chainConfig)
txCtx := core.NewEVMTxContext(msg)
// Trace the transaction and return
return transactions.TraceTx(ctx, msg, blockCtx, txCtx, ibs, config, chainConfig, stream, api.evmCallTimeout)
@@ -472,7 +472,7 @@ func (api *PrivateDebugAPIImpl) TraceCallMany(ctx context.Context, bundles []Bun
return hash
}
- blockCtx = core.NewEVMBlockContext(header, getHash, api.engine(), nil /* author */)
+ blockCtx = core.NewEVMBlockContext(header, getHash, api.engine(), nil /* author */, chainConfig)
// Get a new instance of the EVM
evm = vm.NewEVM(blockCtx, txCtx, st, chainConfig, vm.Config{Debug: false})
signer := types.MakeSigner(chainConfig, blockNum, block.Time())
diff --git a/turbo/stages/mock/mock_sentry.go b/turbo/stages/mock/mock_sentry.go
index b7e5ec60f51..ac807c4b4c2 100644
--- a/turbo/stages/mock/mock_sentry.go
+++ b/turbo/stages/mock/mock_sentry.go
@@ -21,6 +21,7 @@ import (
"github.com/erigontech/erigon-lib/chain"
libcommon "github.com/erigontech/erigon-lib/common"
"github.com/erigontech/erigon-lib/common/datadir"
+ "github.com/erigontech/erigon-lib/common/fixedgas"
"github.com/erigontech/erigon-lib/direct"
"github.com/erigontech/erigon-lib/gointerfaces"
proto_downloader "github.com/erigontech/erigon-lib/gointerfaces/downloader"
@@ -310,8 +311,12 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK
shanghaiTime := mock.ChainConfig.ShanghaiTime
cancunTime := mock.ChainConfig.CancunTime
pragueTime := mock.ChainConfig.PragueTime
- maxBlobsPerBlock := mock.ChainConfig.GetMaxBlobsPerBlock()
- mock.TxPool, err = txpool.New(newTxs, mock.DB, poolCfg, kvcache.NewDummy(), *chainID, shanghaiTime, nil /* agraBlock */, cancunTime, pragueTime, maxBlobsPerBlock, nil, logger)
+ maxBlobsPerBlock := mock.ChainConfig.GetMaxBlobsPerBlock(0)
+ maxBlobsPerBlockPrague := mock.ChainConfig.MaxBlobGasPerBlockPrague
+ if maxBlobsPerBlockPrague != nil {
+ *maxBlobsPerBlockPrague = *maxBlobsPerBlockPrague / fixedgas.BlobGasPerBlob
+ }
+ mock.TxPool, err = txpool.New(newTxs, mock.DB, poolCfg, kvcache.NewDummy(), *chainID, shanghaiTime, nil /* agraBlock */, cancunTime, pragueTime, maxBlobsPerBlock, maxBlobsPerBlockPrague, nil, logger)
if err != nil {
tb.Fatal(err)
}
diff --git a/turbo/stages/stageloop.go b/turbo/stages/stageloop.go
index 7b0a49a2f5e..a42f30c7846 100644
--- a/turbo/stages/stageloop.go
+++ b/turbo/stages/stageloop.go
@@ -302,8 +302,13 @@ func (h *Hook) sendNotifications(notifications *shards.Notifications, tx kv.Tx,
pendingBaseFee := misc.CalcBaseFee(h.chainConfig, currentHeader)
pendingBlobFee := h.chainConfig.GetMinBlobGasPrice()
if currentHeader.ExcessBlobGas != nil {
- excessBlobGas := misc.CalcExcessBlobGas(h.chainConfig, currentHeader)
- f, err := misc.GetBlobGasPrice(h.chainConfig, excessBlobGas)
+ nextBlockTime := currentHeader.Time + 1
+ parentHeader := rawdb.ReadHeaderByNumber(tx, currentHeader.Number.Uint64())
+ if parentHeader != nil {
+ nextBlockTime = currentHeader.Time + (currentHeader.Time - parentHeader.Time) // Approximately next block time
+ }
+ excessBlobGas := misc.CalcExcessBlobGas(h.chainConfig, currentHeader, nextBlockTime)
+ f, err := misc.GetBlobGasPrice(h.chainConfig, excessBlobGas, nextBlockTime)
if err != nil {
return err
}
diff --git a/turbo/transactions/call.go b/turbo/transactions/call.go
index da29580bd09..34ff914f0fd 100644
--- a/turbo/transactions/call.go
+++ b/turbo/transactions/call.go
@@ -80,7 +80,7 @@ func DoCall(
if err != nil {
return nil, err
}
- blockCtx := NewEVMBlockContext(engine, header, blockNrOrHash.RequireCanonical, tx, headerReader)
+ blockCtx := NewEVMBlockContext(engine, header, blockNrOrHash.RequireCanonical, tx, headerReader, chainConfig)
txCtx := core.NewEVMTxContext(msg)
evm := vm.NewEVM(blockCtx, txCtx, state, chainConfig, vm.Config{NoBaseFee: true})
@@ -105,8 +105,8 @@ func DoCall(
return result, nil
}
-func NewEVMBlockContext(engine consensus.EngineReader, header *types.Header, requireCanonical bool, tx kv.Tx, headerReader services.HeaderReader) evmtypes.BlockContext {
- return core.NewEVMBlockContext(header, MakeHeaderGetter(requireCanonical, tx, headerReader), engine, nil /* author */)
+func NewEVMBlockContext(engine consensus.EngineReader, header *types.Header, requireCanonical bool, tx kv.Tx, headerReader services.HeaderReader, config *chain.Config) evmtypes.BlockContext {
+ return core.NewEVMBlockContext(header, MakeHeaderGetter(requireCanonical, tx, headerReader), engine, nil /* author */, config)
}
func MakeHeaderGetter(requireCanonical bool, tx kv.Tx, headerReader services.HeaderReader) func(uint64) libcommon.Hash {
@@ -212,7 +212,7 @@ func NewReusableCaller(
return nil, err
}
- blockCtx := NewEVMBlockContext(engine, header, blockNrOrHash.RequireCanonical, tx, headerReader)
+ blockCtx := NewEVMBlockContext(engine, header, blockNrOrHash.RequireCanonical, tx, headerReader, chainConfig)
txCtx := core.NewEVMTxContext(msg)
evm := vm.NewEVM(blockCtx, txCtx, ibs, chainConfig, vm.Config{NoBaseFee: true})
diff --git a/turbo/transactions/tracing.go b/turbo/transactions/tracing.go
index c09780d418d..c953ec11589 100644
--- a/turbo/transactions/tracing.go
+++ b/turbo/transactions/tracing.go
@@ -56,7 +56,7 @@ func ComputeTxEnv(ctx context.Context, engine consensus.EngineReader, block *typ
}
header := block.HeaderNoCopy()
- blockContext := core.NewEVMBlockContext(header, core.GetHashFn(header, getHeader), engine, nil)
+ blockContext := core.NewEVMBlockContext(header, core.GetHashFn(header, getHeader), engine, nil, cfg)
// Recompute transactions up to the target index.
signer := types.MakeSigner(cfg, block.NumberU64(), block.Time())