From e5171495e175b58cfda749bb3b21a3aecc414a86 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> Date: Tue, 28 May 2024 08:37:13 +0800 Subject: [PATCH] feat: check basefee in Curie (#770) * add consensus/misc/eip1559/eip1559_scroll.go * update core/chain_makers.go * add `fees.GetL1BaseFee` * update eth/gasprice/feehistory.go * fix internal/ethapi/api.go & eth/filters/api.go * update graphql/graphql.go * update miner/worker.go * update txpool * fix api_backend * fix Curie * update core/state_transition.go * update internal/ethapi/transaction_args.go * fix cmd/evm/internal/t8ntool/transition.go * update core/state_processor_test.go * update core/txpool/blobpool/blobpool_test.go * fix internal/ethapi/api_test.go * update eth/gasprice/gasprice_test.go * update internal/ethapi/transaction_args_test.go * update accounts/abi/bind/backends/simulated.go * update accounts/abi/bind/base.go --- accounts/abi/bind/backends/simulated.go | 12 +++- accounts/abi/bind/base.go | 14 +++-- cmd/evm/internal/t8ntool/transition.go | 13 +++-- consensus/clique/clique.go | 2 +- consensus/ethash/consensus.go | 2 +- consensus/misc/eip1559/eip1559.go | 4 ++ consensus/misc/eip1559/eip1559_scroll.go | 73 ++++++++++++++++++++++++ consensus/misc/eip1559/eip1559_test.go | 4 ++ core/chain_makers.go | 25 ++++---- core/genesis.go | 16 +++--- core/state_processor_test.go | 5 +- core/state_transition.go | 11 +++- core/txpool/blobpool/blobpool.go | 5 +- core/txpool/blobpool/blobpool_test.go | 3 +- core/txpool/legacypool/legacypool.go | 6 +- core/txpool/validation.go | 4 +- eth/api_backend.go | 4 ++ eth/filters/api.go | 21 ++++++- eth/filters/filter_system.go | 3 + eth/gasprice/feehistory.go | 11 +++- eth/gasprice/gasprice.go | 2 + eth/gasprice/gasprice_test.go | 5 ++ graphql/graphql.go | 14 ++++- internal/ethapi/api.go | 52 ++++++++++++++--- internal/ethapi/api_test.go | 3 + internal/ethapi/backend.go | 1 + internal/ethapi/transaction_args.go | 38 ++++++------ internal/ethapi/transaction_args_test.go | 4 ++ les/api_backend.go | 5 ++ miner/worker.go | 16 ++++-- rollup/fees/rollup_fee.go | 4 ++ 31 files changed, 301 insertions(+), 81 deletions(-) create mode 100644 consensus/misc/eip1559/eip1559_scroll.go diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 1350b8416d..12e36e8aaf 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -646,7 +646,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) { return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") } - if !b.blockchain.Config().IsLondon(header.Number) { + if !b.blockchain.Config().IsCurie(header.Number) { // If there's no basefee, then it must be a non-1559 execution if call.GasPrice == nil { call.GasPrice = new(big.Int) @@ -668,7 +668,11 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM // Backfill the legacy gasPrice for EVM execution, unless we're all zeroes call.GasPrice = new(big.Int) if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 { - call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, header.BaseFee), call.GasFeeCap) + if header.BaseFee != nil { + call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, header.BaseFee), call.GasFeeCap) + } else { + call.GasPrice = math.BigMin(call.GasTipCap, call.GasFeeCap) + } } } } @@ -980,3 +984,7 @@ func nullSubscription() event.Subscription { return nil }) } + +func (fb *filterBackend) StateAt(root common.Hash) (*state.StateDB, error) { + return fb.bc.StateAt(root) +} diff --git a/accounts/abi/bind/base.go b/accounts/abi/bind/base.go index 6da15f147c..5d46b01e46 100644 --- a/accounts/abi/bind/base.go +++ b/accounts/abi/bind/base.go @@ -277,10 +277,14 @@ func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Add // Estimate FeeCap gasFeeCap := opts.GasFeeCap if gasFeeCap == nil { - gasFeeCap = new(big.Int).Add( - gasTipCap, - new(big.Int).Mul(head.BaseFee, big.NewInt(basefeeWiggleMultiplier)), - ) + if head.BaseFee != nil { + gasFeeCap = new(big.Int).Add( + gasTipCap, + new(big.Int).Mul(head.BaseFee, big.NewInt(basefeeWiggleMultiplier)), + ) + } else { + gasFeeCap = new(big.Int).Set(gasTipCap) + } } if gasFeeCap.Cmp(gasTipCap) < 0 { return nil, fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", gasFeeCap, gasTipCap) @@ -313,7 +317,7 @@ func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Add func (c *BoundContract) createLegacyTx(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) { if opts.GasFeeCap != nil || opts.GasTipCap != nil { - return nil, errors.New("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet") + return nil, errors.New("maxFeePerGas or maxPriorityFeePerGas specified but curie is not active yet") } // Normalize value value := opts.Value diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go index 600bc460f7..25661c7c09 100644 --- a/cmd/evm/internal/t8ntool/transition.go +++ b/cmd/evm/internal/t8ntool/transition.go @@ -81,6 +81,8 @@ type input struct { Env *stEnv `json:"env,omitempty"` Txs []*txWithKey `json:"txs,omitempty"` TxRlp string `json:"txsRlp,omitempty"` + + ParentL1BaseFee *big.Int `json:"parentL1BaseFee,omitempty"` } func Transition(ctx *cli.Context) error { @@ -195,7 +197,7 @@ func Transition(ctx *cli.Context) error { if txs, err = loadTransactions(txStr, inputData, prestate.Env, chainConfig); err != nil { return err } - if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil { + if err := applyCurieChecks(&prestate.Env, chainConfig, inputData.ParentL1BaseFee); err != nil { return err } if err := applyShanghaiChecks(&prestate.Env, chainConfig); err != nil { @@ -338,8 +340,8 @@ func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *pa return signUnsignedTransactions(txsWithKeys, signer) } -func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error { - if !chainConfig.IsLondon(big.NewInt(int64(env.Number))) { +func applyCurieChecks(env *stEnv, chainConfig *params.ChainConfig, parentL1BaseFee *big.Int) error { + if !chainConfig.IsCurie(big.NewInt(int64(env.Number))) { return nil } // Sanity check, to not `panic` in state_transition @@ -350,12 +352,15 @@ func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error { if env.ParentBaseFee == nil || env.Number == 0 { return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section")) } + if parentL1BaseFee == nil { + return errors.New("EIP-1559 config but missing 'parentL1BaseFee' for calculating basefee") + } env.BaseFee = eip1559.CalcBaseFee(chainConfig, &types.Header{ Number: new(big.Int).SetUint64(env.Number - 1), BaseFee: env.ParentBaseFee, GasUsed: env.ParentGasUsed, GasLimit: env.ParentGasLimit, - }) + }, parentL1BaseFee) return nil } diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 7e3e185065..8e6da2ddfa 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -336,7 +336,7 @@ func (c *Clique) verifyCascadingFields(chain consensus.ChainHeaderReader, header if header.GasUsed > header.GasLimit { return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) } - if !chain.Config().IsLondon(header.Number) { + if !chain.Config().IsCurie(header.Number) { // Verify BaseFee not present before EIP-1559 fork. if header.BaseFee != nil { return fmt.Errorf("invalid baseFee before fork: have %d, want ", header.BaseFee) diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index bb6b2257e3..a6a2e596e2 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -247,7 +247,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) } // Verify the block's gas usage and (if applicable) verify the base fee. - if !chain.Config().IsLondon(header.Number) { + if !chain.Config().IsCurie(header.Number) { // Verify BaseFee not present before EIP-1559 fork. if header.BaseFee != nil { return fmt.Errorf("invalid baseFee before fork: have %d, expected 'nil'", header.BaseFee) diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go index 84b82c4c49..c1dfbee455 100644 --- a/consensus/misc/eip1559/eip1559.go +++ b/consensus/misc/eip1559/eip1559.go @@ -16,6 +16,8 @@ package eip1559 +/* + import ( "errors" "fmt" @@ -93,3 +95,5 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { return math.BigMax(baseFee, common.Big0) } } + +*/ diff --git a/consensus/misc/eip1559/eip1559_scroll.go b/consensus/misc/eip1559/eip1559_scroll.go new file mode 100644 index 0000000000..eabcad19c8 --- /dev/null +++ b/consensus/misc/eip1559/eip1559_scroll.go @@ -0,0 +1,73 @@ +// Copyright 2021 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 . + +package eip1559 + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/consensus/misc" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" +) + +// Protocol-enforced maximum L2 base fee. +// We would only go above this if L1 base fee hits 700 Gwei. +const MaximumL2BaseFee = 10000000000 + +// VerifyEIP1559Header verifies some header attributes which were changed in EIP-1559, +// - gas limit check +// - basefee check +func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Header) error { + // Verify that the gas limit remains within allowed bounds + if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil { + return err + } + // Verify the header is not malformed + if header.BaseFee == nil { + return fmt.Errorf("header is missing baseFee") + } + // note: we do not verify L2 base fee, the sequencer has the + // right to set any base fee below the maximum. L2 base fee + // is not subject to L2 consensus or zk verification. + if header.BaseFee.Cmp(big.NewInt(MaximumL2BaseFee)) > 0 { + return fmt.Errorf("invalid baseFee: have %s, maximum %d", header.BaseFee, MaximumL2BaseFee) + } + return nil +} + +// CalcBaseFee calculates the basefee of the header. +func CalcBaseFee(config *params.ChainConfig, parent *types.Header, parentL1BaseFee *big.Int) *big.Int { + l2SequencerFee := big.NewInt(10000000) // 0.01 Gwei + provingFee := big.NewInt(140000000) // 0.14 Gwei + + // L1_base_fee * 0.014 + verificationFee := parentL1BaseFee + verificationFee = new(big.Int).Mul(verificationFee, big.NewInt(14)) + verificationFee = new(big.Int).Div(verificationFee, big.NewInt(1000)) + + baseFee := big.NewInt(0) + baseFee.Add(baseFee, l2SequencerFee) + baseFee.Add(baseFee, provingFee) + baseFee.Add(baseFee, verificationFee) + + if baseFee.Cmp(big.NewInt(MaximumL2BaseFee)) > 0 { + baseFee = big.NewInt(MaximumL2BaseFee) + } + + return baseFee +} diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go index b5afdf0fe5..12a66a0b95 100644 --- a/consensus/misc/eip1559/eip1559_test.go +++ b/consensus/misc/eip1559/eip1559_test.go @@ -16,6 +16,8 @@ package eip1559 +/* + import ( "math/big" "testing" @@ -129,3 +131,5 @@ func TestCalcBaseFee(t *testing.T) { } } } + +*/ diff --git a/core/chain_makers.go b/core/chain_makers.go index 41feba7fec..39adb12ec0 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rollup/fees" "github.com/ethereum/go-ethereum/trie" ) @@ -179,7 +180,11 @@ func (b *BlockGen) Timestamp() uint64 { // BaseFee returns the EIP-1559 base fee of the block being generated. func (b *BlockGen) BaseFee() *big.Int { - return new(big.Int).Set(b.header.BaseFee) + if b.header.BaseFee != nil { + return new(big.Int).Set(b.header.BaseFee) + } else { + return big.NewInt(0) + } } // AddUncheckedReceipt forcefully adds a receipts to the block without a @@ -217,12 +222,9 @@ func (b *BlockGen) AddUncle(h *types.Header) { // The gas limit and price should be derived from the parent h.GasLimit = parent.GasLimit - if b.config.IsLondon(h.Number) { - h.BaseFee = eip1559.CalcBaseFee(b.config, parent) - if !b.config.IsLondon(parent.Number) { - parentGasLimit := parent.GasLimit * b.config.ElasticityMultiplier() - h.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit) - } + if b.config.IsCurie(h.Number) { + parentL1BaseFee := fees.GetL1BaseFee(b.statedb) + h.BaseFee = eip1559.CalcBaseFee(b.config, parent, parentL1BaseFee) } b.uncles = append(b.uncles, h) } @@ -409,12 +411,9 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S Number: new(big.Int).Add(parent.Number(), common.Big1), Time: time, } - if chain.Config().IsLondon(header.Number) { - header.BaseFee = eip1559.CalcBaseFee(chain.Config(), parent.Header()) - if !chain.Config().IsLondon(parent.Number()) { - parentGasLimit := parent.GasLimit() * chain.Config().ElasticityMultiplier() - header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit) - } + if chain.Config().IsCurie(header.Number) { + parentL1BaseFee := fees.GetL1BaseFee(state) + header.BaseFee = eip1559.CalcBaseFee(chain.Config(), parent.Header(), parentL1BaseFee) } if chain.Config().IsCancun(header.Number, header.Time) { var ( diff --git a/core/genesis.go b/core/genesis.go index 504aadabd9..cf3cb950d6 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -450,14 +451,13 @@ func (g *Genesis) ToBlock() *types.Block { if g.Difficulty == nil && g.Mixhash == (common.Hash{}) { head.Difficulty = params.GenesisDifficulty } - // TODO: fix basefee - // if g.Config != nil && g.Config.IsLondon(common.Big0) { - // if g.BaseFee != nil { - // head.BaseFee = g.BaseFee - // } else { - // head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee) - // } - // } + if g.Config != nil && g.Config.IsCurie(common.Big0) { + if g.BaseFee != nil { + head.BaseFee = g.BaseFee + } else { + head.BaseFee = eip1559.CalcBaseFee(g.Config, nil, big.NewInt(0)) + } + } var withdrawals []*types.Withdrawal // if conf := g.Config; conf != nil { // num := big.NewInt(int64(g.Number)) diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 6c6ef5adfd..5b314b7d21 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -376,8 +376,9 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr Time: parent.Time() + 10, UncleHash: types.EmptyUncleHash, } - if config.IsLondon(header.Number) { - header.BaseFee = eip1559.CalcBaseFee(config, parent.Header()) + if config.IsCurie(header.Number) { + parentL1BaseFee := big.NewInt(1000000000) // 1 gwei + header.BaseFee = eip1559.CalcBaseFee(config, parent.Header(), parentL1BaseFee) } if config.IsShanghai(header.Number, header.Time) { header.WithdrawalsHash = &types.EmptyWithdrawalsHash diff --git a/core/state_transition.go b/core/state_transition.go index df1867c7bf..bce05cb99c 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -335,6 +335,7 @@ func (st *StateTransition) preCheck() error { } // Make sure that transaction gasFeeCap is greater than the baseFee (post london) + // Note: Logically, this should be `IsCurie`, but we keep `IsLondon` to ensure backward compatibility. if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) { // Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call) if !st.evm.Config.NoBaseFee || msg.GasFeeCap.BitLen() > 0 || msg.GasTipCap.BitLen() > 0 { @@ -352,7 +353,11 @@ func (st *StateTransition) preCheck() error { } // This will panic if baseFee is nil, but basefee presence is verified // as part of header validation. - if msg.GasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 { + if st.evm.Context.BaseFee != nil && msg.GasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 { + return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow, + msg.From.Hex(), msg.GasFeeCap, st.evm.Context.BaseFee) + } + if st.evm.Context.BaseFee == nil && msg.GasFeeCap.Cmp(big.NewInt(0)) < 0 { return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow, msg.From.Hex(), msg.GasFeeCap, st.evm.Context.BaseFee) } @@ -479,7 +484,9 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { st.refundGas(params.RefundQuotientEIP3529) } effectiveTip := msg.GasPrice - if rules.IsLondon { + + // only burn the base fee if the fee vault is not enabled + if rules.IsCurie && !st.evm.ChainConfig().Scroll.FeeVaultEnabled() { effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee)) } diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index 83f3731797..22aa8540be 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -41,6 +41,7 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rollup/fees" "github.com/holiman/billy" "github.com/holiman/uint256" ) @@ -399,7 +400,7 @@ func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Addr p.recheck(addr, nil) } var ( - basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head)) + basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head, fees.GetL1BaseFee(p.state))) blobfee = uint256.MustFromBig(big.NewInt(params.BlobTxMinBlobGasprice)) ) if p.head.ExcessBlobGas != nil { @@ -782,7 +783,7 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) { } // Reset the price heap for the new set of basefee/blobfee pairs var ( - basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), newHead)) + basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), newHead, fees.GetL1BaseFee(p.state))) blobfee = uint256.MustFromBig(big.NewInt(params.BlobTxMinBlobGasprice)) ) if newHead.ExcessBlobGas != nil { diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go index 8914301e14..bfc37d5c5e 100644 --- a/core/txpool/blobpool/blobpool_test.go +++ b/core/txpool/blobpool/blobpool_test.go @@ -109,12 +109,13 @@ func (bc *testBlockChain) CurrentBlock() *types.Header { mid := new(big.Int).Add(lo, hi) mid.Div(mid, big.NewInt(2)) + parentL1BaseFee := big.NewInt(1000000000) // 1 gwei if eip1559.CalcBaseFee(bc.config, &types.Header{ Number: blockNumber, GasLimit: gasLimit, GasUsed: 0, BaseFee: mid, - }).Cmp(bc.basefee.ToBig()) > 0 { + }, parentL1BaseFee).Cmp(bc.basefee.ToBig()) > 0 { hi = mid } else { lo = mid diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 3dcefd683d..e441d58874 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -37,6 +37,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rollup/fees" ) const ( @@ -1287,8 +1288,9 @@ func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest, if reset != nil { pool.demoteUnexecutables() if reset.newHead != nil { - if pool.chainconfig.IsLondon(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) { - pendingBaseFee := eip1559.CalcBaseFee(pool.chainconfig, reset.newHead) + if pool.chainconfig.IsCurie(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) { + l1BaseFee := fees.GetL1BaseFee(pool.currentState) + pendingBaseFee := eip1559.CalcBaseFee(pool.chainconfig, reset.newHead, l1BaseFee) pool.priced.SetBaseFee(pendingBaseFee) } else { pool.priced.Reheap() diff --git a/core/txpool/validation.go b/core/txpool/validation.go index 4cee97b254..eeba1d8255 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -58,10 +58,10 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types return fmt.Errorf("%w: transaction size %v, limit %v", ErrOversizedData, tx.Size(), opts.MaxSize) } // Ensure only transactions that have been enabled are accepted - if !opts.Config.IsBerlin(head.Number) && tx.Type() != types.LegacyTxType { + if !opts.Config.IsCurie(head.Number) && tx.Type() != types.LegacyTxType { return fmt.Errorf("%w: type %d rejected, pool not yet in Berlin", core.ErrTxTypeNotSupported, tx.Type()) } - if !opts.Config.IsLondon(head.Number) && tx.Type() == types.DynamicFeeTxType { + if !opts.Config.IsCurie(head.Number) && tx.Type() == types.DynamicFeeTxType { return fmt.Errorf("%w: type %d rejected, pool not yet in London", core.ErrTxTypeNotSupported, tx.Type()) } if !opts.Config.IsCancun(head.Number, head.Time) && tx.Type() == types.BlobTxType { diff --git a/eth/api_backend.go b/eth/api_backend.go index 1374a352c8..8fc2f72054 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -432,3 +432,7 @@ func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, re func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) } + +func (b *EthAPIBackend) StateAt(root common.Hash) (*state.StateDB, error) { + return b.eth.BlockChain().StateAt(root) +} diff --git a/eth/filters/api.go b/eth/filters/api.go index 0e42cd4d8c..06fb4b6ca0 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -30,6 +30,8 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rollup/fees" "github.com/ethereum/go-ethereum/rpc" ) @@ -164,9 +166,17 @@ func (api *FilterAPI) NewPendingTransactions(ctx context.Context, fullTx *bool) // To keep the original behaviour, send a single tx hash in one notification. // TODO(rjl493456442) Send a batch of tx hashes in one notification latest := api.sys.backend.CurrentHeader() + + state, err := api.sys.backend.StateAt(latest.Root) + if err != nil || state == nil { + log.Error("State not found", "number", latest.Number, "hash", latest.Hash().Hex(), "state", state, "err", err) + continue + } + l1BaseFee := fees.GetL1BaseFee(state) + for _, tx := range txs { if fullTx != nil && *fullTx { - rpcTx := ethapi.NewRPCPendingTransaction(tx, latest, chainConfig) + rpcTx := ethapi.NewRPCPendingTransaction(tx, latest, chainConfig, l1BaseFee) notifier.Notify(rpcSub.ID, rpcTx) } else { notifier.Notify(rpcSub.ID, tx.Hash()) @@ -438,9 +448,16 @@ func (api *FilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) { return returnHashes(hashes), nil case PendingTransactionsSubscription: if f.fullTx { + state, err := api.sys.backend.StateAt(latest.Root) + if err != nil || state == nil { + log.Error("State not found", "number", latest.Number, "hash", latest.Hash().Hex(), "state", state, "err", err) + return nil, errors.New("state not found") + } + l1BaseFee := fees.GetL1BaseFee(state) + txs := make([]*ethapi.RPCTransaction, 0, len(f.txs)) for _, tx := range f.txs { - txs = append(txs, ethapi.NewRPCPendingTransaction(tx, latest, chainConfig)) + txs = append(txs, ethapi.NewRPCPendingTransaction(tx, latest, chainConfig, l1BaseFee)) } f.txs = nil return txs, nil diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go index 35e396c23e..8ec38fda9b 100644 --- a/eth/filters/filter_system.go +++ b/eth/filters/filter_system.go @@ -32,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" @@ -65,6 +66,8 @@ type Backend interface { GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) PendingBlockAndReceipts() (*types.Block, types.Receipts) + StateAt(root common.Hash) (*state.StateDB, error) + CurrentHeader() *types.Header ChainConfig() *params.ChainConfig SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription diff --git a/eth/gasprice/feehistory.go b/eth/gasprice/feehistory.go index f10cd9e02b..4bd4f03cbc 100644 --- a/eth/gasprice/feehistory.go +++ b/eth/gasprice/feehistory.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rollup/fees" "github.com/ethereum/go-ethereum/rpc" "golang.org/x/exp/slices" ) @@ -82,8 +83,14 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) { if bf.results.baseFee = bf.header.BaseFee; bf.results.baseFee == nil { bf.results.baseFee = new(big.Int) } - if chainconfig.IsLondon(big.NewInt(int64(bf.blockNumber + 1))) { - bf.results.nextBaseFee = eip1559.CalcBaseFee(chainconfig, bf.header) + if chainconfig.IsCurie(big.NewInt(int64(bf.blockNumber + 1))) { + state, err := oracle.backend.StateAt(bf.header.Root) + if err != nil || state == nil { + log.Error("State not found", "number", bf.header.Number, "hash", bf.header.Hash().Hex(), "state", state, "err", err) + return + } + l1BaseFee := fees.GetL1BaseFee(state) + bf.results.nextBaseFee = eip1559.CalcBaseFee(chainconfig, bf.header, l1BaseFee) } else { bf.results.nextBaseFee = new(big.Int) } diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index b719649811..33807a14bc 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/lru" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" @@ -57,6 +58,7 @@ type OracleBackend interface { PendingBlockAndReceipts() (*types.Block, types.Receipts) ChainConfig() *params.ChainConfig SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription + StateAt(root common.Hash) (*state.StateDB, error) } // Oracle recommends gas prices based on the content of recent diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go index 5a842d26b7..105b5f411b 100644 --- a/eth/gasprice/gasprice_test.go +++ b/eth/gasprice/gasprice_test.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" @@ -117,6 +118,10 @@ func (b *testBackend) teardown() { b.chain.Stop() } +func (b *testBackend) StateAt(root common.Hash) (*state.StateDB, error) { + return b.chain.StateAt(root) +} + // newTestBackend creates a test backend. OBS: don't forget to invoke tearDown // after use, otherwise the blockchain instance will mem-leak via goroutines. func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBackend { diff --git a/graphql/graphql.go b/graphql/graphql.go index ec7382f80a..d5c3695230 100644 --- a/graphql/graphql.go +++ b/graphql/graphql.go @@ -36,7 +36,9 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rollup/fees" "github.com/ethereum/go-ethereum/rpc" ) @@ -769,11 +771,19 @@ func (b *Block) NextBaseFeePerGas(ctx context.Context) (*hexutil.Big, error) { chaincfg := b.r.backend.ChainConfig() if header.BaseFee == nil { // Make sure next block doesn't enable EIP-1559 - if !chaincfg.IsLondon(new(big.Int).Add(header.Number, common.Big1)) { + if !chaincfg.IsCurie(new(big.Int).Add(header.Number, common.Big1)) { return nil, nil } } - nextBaseFee := eip1559.CalcBaseFee(chaincfg, header) + + state, err := b.r.backend.StateAt(header.Root) + if err != nil { + log.Error("Failed to get state", "err", err) + return nil, err + } + l1BaseFee := fees.GetL1BaseFee(state) + + nextBaseFee := eip1559.CalcBaseFee(chaincfg, header, l1BaseFee) return (*hexutil.Big)(nextBaseFee), nil } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index aa86878ff3..dcec75f93c 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -169,11 +169,20 @@ func (s *TxPoolAPI) Content() map[string]map[string]map[string]*RPCTransaction { } pending, queue := s.b.TxPoolContent() curHeader := s.b.CurrentHeader() + + // get latest L1 base fee + state, err := s.b.StateAt(curHeader.Root) + if err != nil || state == nil { + log.Error("State not found", "number", curHeader.Number, "hash", curHeader.Hash().Hex(), "state", state, "err", err) + return nil + } + l1BaseFee := fees.GetL1BaseFee(state) + // Flatten the pending transactions for account, txs := range pending { dump := make(map[string]*RPCTransaction) for _, tx := range txs { - dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig()) + dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig(), l1BaseFee) } content["pending"][account.Hex()] = dump } @@ -181,7 +190,7 @@ func (s *TxPoolAPI) Content() map[string]map[string]map[string]*RPCTransaction { for account, txs := range queue { dump := make(map[string]*RPCTransaction) for _, tx := range txs { - dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig()) + dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig(), l1BaseFee) } content["queued"][account.Hex()] = dump } @@ -194,17 +203,25 @@ func (s *TxPoolAPI) ContentFrom(addr common.Address) map[string]map[string]*RPCT pending, queue := s.b.TxPoolContentFrom(addr) curHeader := s.b.CurrentHeader() + // get latest L1 base fee + state, err := s.b.StateAt(curHeader.Root) + if err != nil || state == nil { + log.Error("State not found", "number", curHeader.Number, "hash", curHeader.Hash().Hex(), "state", state, "err", err) + return nil + } + l1BaseFee := fees.GetL1BaseFee(state) + // Build the pending transactions dump := make(map[string]*RPCTransaction, len(pending)) for _, tx := range pending { - dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig()) + dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig(), l1BaseFee) } content["pending"] = dump // Build the queued transactions dump = make(map[string]*RPCTransaction, len(queue)) for _, tx := range queue { - dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig()) + dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig(), l1BaseFee) } content["queued"] = dump @@ -1599,14 +1616,14 @@ func effectiveGasPrice(tx *types.Transaction, baseFee *big.Int) *big.Int { } // NewRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation -func NewRPCPendingTransaction(tx *types.Transaction, current *types.Header, config *params.ChainConfig) *RPCTransaction { +func NewRPCPendingTransaction(tx *types.Transaction, current *types.Header, config *params.ChainConfig, l1BaseFee *big.Int) *RPCTransaction { var ( baseFee *big.Int blockNumber = uint64(0) blockTime = uint64(0) ) if current != nil { - baseFee = eip1559.CalcBaseFee(config, current) + baseFee = eip1559.CalcBaseFee(config, current, l1BaseFee) blockNumber = current.Number.Uint64() blockTime = current.Time } @@ -1827,7 +1844,17 @@ func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.H } // No finalized transaction, try to retrieve it from the pool if tx := s.b.GetPoolTransaction(hash); tx != nil { - return NewRPCPendingTransaction(tx, s.b.CurrentHeader(), s.b.ChainConfig()), nil + curHeader := s.b.CurrentHeader() + + // get latest L1 base fee + state, err := s.b.StateAt(curHeader.Root) + if err != nil || state == nil { + log.Error("State not found", "number", curHeader.Number, "hash", curHeader.Hash().Hex(), "state", state, "err", err) + return nil, fmt.Errorf("cannot get L1 base fee, state not found") + } + l1BaseFee := fees.GetL1BaseFee(state) + + return NewRPCPendingTransaction(tx, s.b.CurrentHeader(), s.b.ChainConfig(), l1BaseFee), nil } // Transaction unknown, return as such @@ -2101,10 +2128,19 @@ func (s *TransactionAPI) PendingTransactions() ([]*RPCTransaction, error) { } curHeader := s.b.CurrentHeader() transactions := make([]*RPCTransaction, 0, len(pending)) + + // get latest L1 base fee + state, err := s.b.StateAt(curHeader.Root) + if err != nil || state == nil { + log.Error("State not found", "number", curHeader.Number, "hash", curHeader.Hash().Hex(), "state", state, "err", err) + return nil, fmt.Errorf("cannot get L1 base fee, state not found") + } + l1BaseFee := fees.GetL1BaseFee(state) + for _, tx := range pending { from, _ := types.Sender(s.signer, tx) if _, exists := accounts[from]; exists { - transactions = append(transactions, NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())) + transactions = append(transactions, NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig(), l1BaseFee)) } } return transactions, nil diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 84debc2521..ce3af293cf 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -604,6 +604,9 @@ func (b testBackend) BloomStatus() (uint64, uint64) { panic("implement me") } func (b testBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) { panic("implement me") } +func (b testBackend) StateAt(root common.Hash) (*state.StateDB, error) { + return b.chain.StateAt(root) +} func TestEstimateGas(t *testing.T) { t.Parallel() diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 458fb811ed..f38729d889 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -65,6 +65,7 @@ type Backend interface { BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) + StateAt(root common.Hash) (*state.StateDB, error) PendingBlockAndReceipts() (*types.Block, types.Receipts) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) GetTd(ctx context.Context, hash common.Hash) *big.Int diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index e4cf81a3f4..d53ca87092 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -138,7 +138,7 @@ func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) erro return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") } // If the tx has completely specified a fee mechanism, no default is needed. This allows users - // who are not yet synced past London to get defaults for other tx values. See + // who are not yet synced past Curie to get defaults for other tx values. See // https://github.com/ethereum/go-ethereum/pull/23274 for more information. eip1559ParamsSet := args.MaxFeePerGas != nil && args.MaxPriorityFeePerGas != nil if (args.GasPrice != nil && !eip1559ParamsSet) || (args.GasPrice == nil && eip1559ParamsSet) { @@ -148,18 +148,18 @@ func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) erro } return nil } - // Now attempt to fill in default value depending on whether London is active or not. + // Now attempt to fill in default value depending on whether Curie is active or not. head := b.CurrentHeader() - if b.ChainConfig().IsLondon(head.Number) { - // London is active, set maxPriorityFeePerGas and maxFeePerGas. - if err := args.setLondonFeeDefaults(ctx, head, b); err != nil { + if b.ChainConfig().IsCurie(head.Number) { + // Curie is active, set maxPriorityFeePerGas and maxFeePerGas. + if err := args.setCurieFeeDefaults(ctx, head, b); err != nil { return err } } else { if args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil { - return errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active") + return errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before Curie is active") } - // London not active, set gas price. + // Curie not active, set gas price. price, err := b.SuggestGasTipCap(ctx) if err != nil { return err @@ -169,8 +169,8 @@ func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) erro return nil } -// setLondonFeeDefaults fills in reasonable default fee values for unspecified fields. -func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *types.Header, b Backend) error { +// setCurieFeeDefaults fills in reasonable default fee values for unspecified fields. +func (args *TransactionArgs) setCurieFeeDefaults(ctx context.Context, head *types.Header, b Backend) error { // Set maxPriorityFeePerGas if it is missing. if args.MaxPriorityFeePerGas == nil { tip, err := b.SuggestGasTipCap(ctx) @@ -181,13 +181,19 @@ func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *typ } // Set maxFeePerGas if it is missing. if args.MaxFeePerGas == nil { - // Set the max fee to be 2 times larger than the previous block's base fee. - // The additional slack allows the tx to not become invalidated if the base - // fee is rising. - val := new(big.Int).Add( - args.MaxPriorityFeePerGas.ToInt(), - new(big.Int).Mul(head.BaseFee, big.NewInt(2)), - ) + var val *big.Int + if head.BaseFee != nil { + // Set the max fee to be 2 times larger than the previous block's base fee. + // The additional slack allows the tx to not become invalidated if the base + // fee is rising. + val = new(big.Int).Add( + args.MaxPriorityFeePerGas.ToInt(), + new(big.Int).Mul(head.BaseFee, big.NewInt(2)), + ) + } else { + val = new(big.Int).Set( + (*big.Int)(args.MaxPriorityFeePerGas)) + } args.MaxFeePerGas = (*hexutil.Big)(val) } // Both EIP-1559 fee parameters are now set; sanity check them. diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index 9161d5e681..ddd7ea7b61 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -343,3 +343,7 @@ func (b *backendMock) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) } func (b *backendMock) Engine() consensus.Engine { return nil } + +func (b *backendMock) StateAt(root common.Hash) (*state.StateDB, error) { + return nil, nil +} diff --git a/les/api_backend.go b/les/api_backend.go index 0347b43c35..11f91f89cb 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -19,6 +19,7 @@ package les import ( "context" "errors" + "fmt" "math/big" "time" @@ -336,3 +337,7 @@ func (b *LesApiBackend) StateAtBlock(ctx context.Context, block *types.Block, re func (b *LesApiBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) } + +func (b *LesApiBackend) StateAt(root common.Hash) (*state.StateDB, error) { + return nil, fmt.Errorf("StateAt is not supported in LES protocol") +} diff --git a/miner/worker.go b/miner/worker.go index 9e57560e23..0314216ff8 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -39,6 +39,7 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rollup/circuitcapacitychecker" + "github.com/ethereum/go-ethereum/rollup/fees" "github.com/ethereum/go-ethereum/rollup/tracing" "github.com/ethereum/go-ethereum/trie" ) @@ -1346,13 +1347,16 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) { if genParams.random != (common.Hash{}) { header.MixDigest = genParams.random } - // Set baseFee and GasLimit if we are on an EIP-1559 chain - if w.chainConfig.IsLondon(header.Number) { - header.BaseFee = eip1559.CalcBaseFee(w.chainConfig, parent) - if !w.chainConfig.IsLondon(parent.Number) { - parentGasLimit := parent.GasLimit * w.chainConfig.ElasticityMultiplier() - header.GasLimit = core.CalcGasLimit(parentGasLimit, w.config.GasCeil) + // Set baseFee if we are on an EIP-1559 chain + if w.chainConfig.IsCurie(header.Number) { + state, err := w.chain.StateAt(parent.Root) + if err != nil { + log.Error("Failed to create mining context", "err", err) + return nil, err } + parentL1BaseFee := fees.GetL1BaseFee(state) + header.BaseFee = eip1559.CalcBaseFee(w.chainConfig, parent, parentL1BaseFee) + } // Apply EIP-4844, EIP-4788. if w.chainConfig.IsCancun(header.Number, header.Time) { diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 76755e98d8..33efebc2b5 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -187,3 +187,7 @@ func CalculateL1DataFee(tx *types.Transaction, state StateDB) (*big.Int, error) l1DataFee := calculateEncodedL1DataFee(raw, overhead, l1BaseFee, scalar) return l1DataFee, nil } + +func GetL1BaseFee(state StateDB) *big.Int { + return state.GetState(rcfg.L1GasPriceOracleAddress, rcfg.L1BaseFeeSlot).Big() +}