diff --git a/Makefile b/Makefile index 2a0c148d569e..77500dfa5c66 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ test: all # genesis test cd ${PWD}/cmd/geth; go test -test.run TestCustomGenesis # module test - $(GORUN) build/ci.go test ./consensus ./core ./eth ./miner ./node ./trie + $(GORUN) build/ci.go test ./consensus ./core ./eth ./miner ./node ./trie ./rollup/fees lint: ## Run linters. $(GORUN) build/ci.go lint diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index febabccc2b08..949210ae0b3d 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -640,7 +640,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true}) gasPool := new(core.GasPool).AddGas(math.MaxUint64) signer := types.MakeSigner(b.blockchain.Config(), head.Number) - l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, head.BaseFee, b.blockchain.Config().ChainID, signer, stateDB) + l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, head.BaseFee, b.blockchain.Config(), signer, stateDB, head.Number) if err != nil { return nil, err } diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 6e8cb9f44620..b1f5c13ea0ff 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -148,6 +148,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 { misc.ApplyDAOHardFork(statedb) } + // Apply Curie hard fork + if chainConfig.CurieBlock != nil && chainConfig.CurieBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 { + misc.ApplyCurieHardFork(statedb) + } for i, tx := range txs { msg, err := tx.AsMessage(signer, pre.Env.BaseFee) @@ -167,7 +171,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, snapshot := statedb.Snapshot() evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, chainConfig, new(big.Int).SetUint64(pre.Env.Number)) if err != nil { log.Info("rejected tx due to fees.CalculateL1DataFee", "index", i, "hash", tx.Hash(), "from", msg.From(), "error", err) rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) diff --git a/consensus/misc/curie.go b/consensus/misc/curie.go new file mode 100644 index 000000000000..e1668b25dc33 --- /dev/null +++ b/consensus/misc/curie.go @@ -0,0 +1,23 @@ +package misc + +import ( + "github.com/scroll-tech/go-ethereum/common" + "github.com/scroll-tech/go-ethereum/core/state" + "github.com/scroll-tech/go-ethereum/log" + "github.com/scroll-tech/go-ethereum/rollup/rcfg" +) + +// ApplyCurieHardFork modifies the state database according to the Curie hard-fork rules, +// updating the bytecode and storage of the L1GasPriceOracle contract. +func ApplyCurieHardFork(statedb *state.StateDB) { + log.Info("Applying Curie hard fork") + + // update contract byte code + statedb.SetCode(rcfg.L1GasPriceOracleAddress, rcfg.CurieL1GasPriceOracleBytecode) + + // initialize new storage slots + statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.IsCurieSlot, common.BytesToHash([]byte{1})) + statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.L1BlobBaseFeeSlot, common.BytesToHash([]byte{1})) + statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.CommitScalarSlot, common.BigToHash(rcfg.InitialCommitScalar)) + statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.BlobScalarSlot, common.BigToHash(rcfg.InitialBlobScalar)) +} diff --git a/core/blockchain_test.go b/core/blockchain_test.go index b0f601f45585..87e7b01b5eb7 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -17,6 +17,7 @@ package core import ( + "encoding/json" "errors" "fmt" "io/ioutil" @@ -39,6 +40,7 @@ import ( "github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/ethdb" "github.com/scroll-tech/go-ethereum/params" + "github.com/scroll-tech/go-ethereum/rollup/rcfg" "github.com/scroll-tech/go-ethereum/trie" ) @@ -3712,3 +3714,78 @@ func TestTransientStorageReset(t *testing.T) { t.Fatalf("Unexpected dirty storage slot") } } + +func TestCurieTransition(t *testing.T) { + // Set fork blocks in config + // (we make a deep copy to avoid interference with other tests) + var config *params.ChainConfig + b, _ := json.Marshal(params.AllEthashProtocolChanges) + json.Unmarshal(b, &config) + config.CurieBlock = big.NewInt(2) + config.DescartesBlock = nil + + var ( + db = rawdb.NewMemoryDatabase() + gspec = &Genesis{Config: config} + genesis = gspec.MustCommit(db) + ) + + blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) + defer blockchain.Stop() + blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, nil) + + if _, err := blockchain.InsertChain(blocks); err != nil { + t.Fatal(err) + } + + latestBlock := uint64(4) + assert.Equal(t, latestBlock, blockchain.CurrentHeader().Number.Uint64()) + + for ii := uint64(0); ii <= latestBlock; ii++ { + block := blockchain.GetBlockByNumber(ii) + + number := block.Number().Uint64() + baseFee := block.BaseFee() + + statedb, _ := state.New(block.Root(), state.NewDatabase(db), nil) + + code := statedb.GetCode(rcfg.L1GasPriceOracleAddress) + codeSize := statedb.GetCodeSize(rcfg.L1GasPriceOracleAddress) + keccakCodeHash := statedb.GetKeccakCodeHash(rcfg.L1GasPriceOracleAddress) + poseidonCodeHash := statedb.GetPoseidonCodeHash(rcfg.L1GasPriceOracleAddress) + + l1BlobBaseFee := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.L1BlobBaseFeeSlot) + commitScalar := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.CommitScalarSlot) + blobScalar := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.BlobScalarSlot) + isCurie := statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.IsCurieSlot) + + if number < config.CurieBlock.Uint64() { + assert.Nil(t, baseFee, "Expected zero base fee before Curie") + + // we don't have predeploys configured in this test, + // so there is no gas oracle deployed before Curie + assert.Nil(t, code) + assert.Equal(t, uint64(0), codeSize) + assert.Equal(t, common.Hash{}, keccakCodeHash) + assert.Equal(t, common.Hash{}, poseidonCodeHash) + + assert.Equal(t, common.Hash{}, l1BlobBaseFee) + assert.Equal(t, common.Hash{}, commitScalar) + assert.Equal(t, common.Hash{}, blobScalar) + assert.Equal(t, common.Hash{}, isCurie) + } else { + assert.NotNil(t, baseFee, "Expected nonzero base fee after Curie") + + // all gas oracle entries updated + assert.NotNil(t, code) + assert.NotEqual(t, uint64(0), codeSize) + assert.NotEqual(t, common.Hash{}, keccakCodeHash) + assert.NotEqual(t, common.Hash{}, poseidonCodeHash) + + assert.NotEqual(t, common.Hash{}, l1BlobBaseFee) + assert.NotEqual(t, common.Hash{}, commitScalar) + assert.NotEqual(t, common.Hash{}, blobScalar) + assert.NotEqual(t, common.Hash{}, isCurie) + } + } +} diff --git a/core/chain_makers.go b/core/chain_makers.go index 143dbb005918..b79d92bf71e4 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -240,6 +240,9 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(b.header.Number) == 0 { misc.ApplyDAOHardFork(statedb) } + if config.CurieBlock != nil && config.CurieBlock.Cmp(b.header.Number) == 0 { + misc.ApplyCurieHardFork(statedb) + } // Execute any user modifications to the block if gen != nil { gen(i, b) diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index 1fc7e02893ab..962f43a3ec91 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -71,7 +71,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c } statedb.SetTxContext(tx.Hash(), i) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, p.config, block.Number()) if err != nil { return } diff --git a/core/state_processor.go b/core/state_processor.go index 95952a4c19aa..8b4671d76768 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -86,6 +86,10 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { misc.ApplyDAOHardFork(statedb) } + // Apply Curie hard fork + if p.config.CurieBlock != nil && p.config.CurieBlock.Cmp(block.Number()) == 0 { + misc.ApplyCurieHardFork(statedb) + } blockContext := NewEVMBlockContext(header, p.bc, p.config, nil) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) processorBlockTransactionGauge.Update(int64(block.Transactions().Len())) @@ -120,7 +124,7 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, config, blockNumber) if err != nil { return nil, err } diff --git a/core/tx_list.go b/core/tx_list.go index 3742d7416e21..f219264260bb 100644 --- a/core/tx_list.go +++ b/core/tx_list.go @@ -29,6 +29,7 @@ import ( "github.com/scroll-tech/go-ethereum/core/state" "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/log" + "github.com/scroll-tech/go-ethereum/params" "github.com/scroll-tech/go-ethereum/rollup/fees" ) @@ -281,7 +282,7 @@ func (l *txList) Overlaps(tx *types.Transaction) bool { // // If the new transaction is accepted into the list, the lists' cost and gas // thresholds are also potentially updated. -func (l *txList) Add(tx *types.Transaction, state *state.StateDB, priceBump uint64) (bool, *types.Transaction) { +func (l *txList) Add(tx *types.Transaction, state *state.StateDB, priceBump uint64, chainconfig *params.ChainConfig, blockNumber *big.Int) (bool, *types.Transaction) { // If there's an older better transaction, abort old := l.txs.Get(tx.Nonce()) if old != nil { @@ -307,9 +308,9 @@ func (l *txList) Add(tx *types.Transaction, state *state.StateDB, priceBump uint } // Otherwise overwrite the old transaction with the current one l1DataFee := big.NewInt(0) - if state != nil { + if state != nil && chainconfig != nil { var err error - l1DataFee, err = fees.CalculateL1DataFee(tx, state) + l1DataFee, err = fees.CalculateL1DataFee(tx, state, chainconfig, blockNumber) if err != nil { log.Error("Failed to calculate L1 data fee", "err", err, "tx", tx) return false, nil diff --git a/core/tx_list_test.go b/core/tx_list_test.go index bd3fee86d8f8..9b1cab4c406b 100644 --- a/core/tx_list_test.go +++ b/core/tx_list_test.go @@ -38,7 +38,7 @@ func TestStrictTxListAdd(t *testing.T) { // Insert the transactions in a random order list := newTxList(true) for _, v := range rand.Perm(len(txs)) { - list.Add(txs[v], nil, DefaultTxPoolConfig.PriceBump) + list.Add(txs[v], nil, DefaultTxPoolConfig.PriceBump, nil, nil) } // Verify internal state if len(list.txs.items) != len(txs) { @@ -65,7 +65,7 @@ func BenchmarkTxListAdd(b *testing.B) { for i := 0; i < b.N; i++ { list := newTxList(true) for _, v := range rand.Perm(len(txs)) { - list.Add(txs[v], nil, DefaultTxPoolConfig.PriceBump) + list.Add(txs[v], nil, DefaultTxPoolConfig.PriceBump, nil, nil) list.Filter(priceLimit, DefaultTxPoolConfig.PriceBump) } } diff --git a/core/tx_pool.go b/core/tx_pool.go index a8454204abf0..7e6bdd58a128 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -248,6 +248,7 @@ type TxPool struct { shanghai bool // Fork indicator whether we are in the Shanghai stage. currentState *state.StateDB // Current state in the blockchain head + currentHead *big.Int // Current blockchain head pendingNonces *txNoncer // Pending state tracking virtual nonces currentMaxGas uint64 // Current gas limit for transaction caps @@ -664,7 +665,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { // 2. If FeeVault is enabled, perform an additional check for L1 data fees. if pool.chainconfig.Scroll.FeeVaultEnabled() { // Get L1 data fee in current state - l1DataFee, err := fees.CalculateL1DataFee(tx, pool.currentState) + l1DataFee, err := fees.CalculateL1DataFee(tx, pool.currentState, pool.chainconfig, pool.currentHead) if err != nil { return fmt.Errorf("failed to calculate L1 data fee, err: %w", err) } @@ -751,7 +752,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e from, _ := types.Sender(pool.signer, tx) // already validated if list := pool.pending[from]; list != nil && list.Overlaps(tx) { // Nonce already pending, check if required price bump is met - inserted, old := list.Add(tx, pool.currentState, pool.config.PriceBump) + inserted, old := list.Add(tx, pool.currentState, pool.config.PriceBump, pool.chainconfig, pool.currentHead) if !inserted { pendingDiscardMeter.Mark(1) return false, ErrReplaceUnderpriced @@ -802,7 +803,7 @@ func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction, local boo pool.queue[from] = newTxList(false) } - inserted, old := pool.queue[from].Add(tx, pool.currentState, pool.config.PriceBump) + inserted, old := pool.queue[from].Add(tx, pool.currentState, pool.config.PriceBump, pool.chainconfig, pool.currentHead) if !inserted { // An older transaction was better, discard this queuedDiscardMeter.Mark(1) @@ -856,7 +857,7 @@ func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.T } list := pool.pending[addr] - inserted, old := list.Add(tx, pool.currentState, pool.config.PriceBump) + inserted, old := list.Add(tx, pool.currentState, pool.config.PriceBump, pool.chainconfig, pool.currentHead) if !inserted { // An older transaction was better, discard this pool.all.Remove(hash) @@ -1357,6 +1358,9 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { pool.eip2718 = pool.chainconfig.IsCurie(next) pool.eip1559 = pool.chainconfig.IsCurie(next) pool.shanghai = pool.chainconfig.IsShanghai(next) + + // Update current head + pool.currentHead = next } // promoteExecutables moves transactions that have become processable from the @@ -1435,7 +1439,7 @@ func (pool *TxPool) executableTxFilter(costLimit *big.Int) func(tx *types.Transa if pool.chainconfig.Scroll.FeeVaultEnabled() { // recheck L1 data fee, as the oracle price may have changed - l1DataFee, err := fees.CalculateL1DataFee(tx, pool.currentState) + l1DataFee, err := fees.CalculateL1DataFee(tx, pool.currentState, pool.chainconfig, pool.currentHead) if err != nil { log.Error("Failed to calculate L1 data fee", "err", err, "tx", tx) return false diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 11eaa365b60c..48e31bb6a72c 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -192,7 +192,7 @@ func (eth *Ethereum) stateAtTransaction(block *types.Block, txIndex int, reexec // Not yet the searched for transaction, execute on top of the current state vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{}) statedb.SetTxContext(tx.Hash(), idx) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, eth.blockchain.Config(), block.Number()) if err != nil { return nil, vm.BlockContext{}, nil, err } diff --git a/eth/tracers/api.go b/eth/tracers/api.go index e4c3957c603d..d9171f4efd85 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -285,7 +285,7 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config TxHash: tx.Hash(), } - l1DataFee, err := fees.CalculateL1DataFee(tx, task.statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, task.statedb, api.backend.ChainConfig(), task.block.Number()) if err != nil { // though it's not a "tracing error", we still need to put it here task.results[i] = &txTraceResult{Error: err.Error()} @@ -545,7 +545,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config ) statedb.SetTxContext(tx.Hash(), i) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number()) if err != nil { log.Warn("Tracing intermediate roots did not complete due to fees.CalculateL1DataFee", "txindex", i, "txhash", tx.Hash(), "err", err) return nil, err @@ -626,7 +626,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac TxHash: txs[task.index].Hash(), } - l1DataFee, err := fees.CalculateL1DataFee(txs[task.index], task.statedb) + l1DataFee, err := fees.CalculateL1DataFee(txs[task.index], task.statedb, api.backend.ChainConfig(), block.Number()) if err != nil { // though it's not a "tracing error", we still need to put it here results[task.index] = &txTraceResult{Error: err.Error()} @@ -651,7 +651,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac msg, _ := tx.AsMessage(signer, block.BaseFee()) statedb.SetTxContext(tx.Hash(), i) vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{}) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number()) if err != nil { failed = err break @@ -769,7 +769,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // Execute the transaction and flush any traces to disk vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf) statedb.SetTxContext(tx.Hash(), i) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number()) if err == nil { _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), l1DataFee) } @@ -834,7 +834,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config * TxIndex: int(index), TxHash: hash, } - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, api.backend.ChainConfig(), block.Number()) if err != nil { return nil, err } @@ -894,7 +894,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc } signer := types.MakeSigner(api.backend.ChainConfig(), block.Number()) - l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, block.BaseFee(), api.backend.ChainConfig().ChainID, signer, statedb) + l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, block.BaseFee(), api.backend.ChainConfig(), signer, statedb, block.Number()) if err != nil { return nil, err } diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 3a209c752b5a..e9928434a981 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -173,7 +173,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block return msg, context, statedb, nil } vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{}) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, b.chainConfig, block.Number()) if err != nil { return nil, vm.BlockContext{}, nil, err } diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index 7fc405b75004..8ef0b653017e 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -193,7 +193,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, test.Genesis.Config, context.BlockNumber) if err != nil { t.Fatalf("failed to calculate l1DataFee: %v", err) } @@ -308,7 +308,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { } evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer}) snap := statedb.Snapshot() - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, test.Genesis.Config, context.BlockNumber) if err != nil { b.Fatalf("failed to calculate l1DataFee: %v", err) } @@ -381,7 +381,7 @@ func TestZeroValueToNotExitCall(t *testing.T) { if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, params.MainnetChainConfig, context.BlockNumber) if err != nil { t.Fatalf("failed to calculate l1DataFee: %v", err) } diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index 7b64f78eeac2..4a18a9245c73 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -112,7 +112,7 @@ func BenchmarkTransactionTrace(b *testing.B) { for i := 0; i < b.N; i++ { snap := statedb.Snapshot() - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, params.AllEthashProtocolChanges, context.BlockNumber) if err != nil { b.Fatal(err) } diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index d89bbcb50a6e..6e1e1393d6b6 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -197,9 +197,13 @@ var genesis = &core.Genesis{ rcfg.L1GasPriceOracleAddress: { Balance: big.NewInt(0), Storage: map[common.Hash]common.Hash{ - rcfg.L1BaseFeeSlot: common.BigToHash(big.NewInt(10000)), - rcfg.OverheadSlot: common.BigToHash(big.NewInt(10000)), - rcfg.ScalarSlot: common.BigToHash(big.NewInt(10000)), + rcfg.L1BaseFeeSlot: common.BigToHash(big.NewInt(10000)), + rcfg.OverheadSlot: common.BigToHash(big.NewInt(10000)), + rcfg.ScalarSlot: common.BigToHash(big.NewInt(10000)), + rcfg.L1BlobBaseFeeSlot: common.BigToHash(big.NewInt(10000)), + rcfg.CommitScalarSlot: common.BigToHash(big.NewInt(10000)), + rcfg.BlobScalarSlot: common.BigToHash(big.NewInt(10000)), + rcfg.IsCurieSlot: common.BytesToHash([]byte{1}), }, }, }, diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 04a498d0f9e5..32f16e8c035b 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -81,9 +81,13 @@ func generateTestChain() (*core.Genesis, []*types.Block) { rcfg.L1GasPriceOracleAddress: { Balance: big.NewInt(0), Storage: map[common.Hash]common.Hash{ - rcfg.L1BaseFeeSlot: common.BigToHash(big.NewInt(10000)), - rcfg.OverheadSlot: common.BigToHash(big.NewInt(10000)), - rcfg.ScalarSlot: common.BigToHash(big.NewInt(10000)), + rcfg.L1BaseFeeSlot: common.BigToHash(big.NewInt(10000)), + rcfg.OverheadSlot: common.BigToHash(big.NewInt(10000)), + rcfg.ScalarSlot: common.BigToHash(big.NewInt(10000)), + rcfg.L1BlobBaseFeeSlot: common.BigToHash(big.NewInt(10000)), + rcfg.CommitScalarSlot: common.BigToHash(big.NewInt(10000)), + rcfg.BlobScalarSlot: common.BigToHash(big.NewInt(10000)), + rcfg.IsCurieSlot: common.BytesToHash([]byte{1}), }, }, }, diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index b41bd33fd84d..b4cf9539ce76 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -952,7 +952,7 @@ func EstimateL1MsgFee(ctx context.Context, b Backend, args TransactionArgs, bloc }() signer := types.MakeSigner(config, header.Number) - return fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config.ChainID, signer, evm.StateDB) + return fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config, signer, evm.StateDB, header.Number) } func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) { @@ -1496,7 +1496,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH return nil, 0, nil, err } signer := types.MakeSigner(b.ChainConfig(), header.Number) - l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, b.ChainConfig().ChainID, signer, statedb) + l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, b.ChainConfig(), signer, statedb, header.Number) if err != nil { return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.toTransaction().Hash(), err) } diff --git a/les/odr_test.go b/les/odr_test.go index 6878e3479ec6..11f254ffd535 100644 --- a/les/odr_test.go +++ b/les/odr_test.go @@ -145,7 +145,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai //vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{}) gp := new(core.GasPool).AddGas(math.MaxUint64) signer := types.MakeSigner(config, header.Number) - l1DataFee, _ := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config.ChainID, signer, statedb) + l1DataFee, _ := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config, signer, statedb, header.Number) result, _ := core.ApplyMessage(vmenv, msg, gp, l1DataFee) res = append(res, result.Return()...) } @@ -159,7 +159,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai vmenv := vm.NewEVM(context, txContext, state, config, vm.Config{NoBaseFee: true}) gp := new(core.GasPool).AddGas(math.MaxUint64) signer := types.MakeSigner(config, header.Number) - l1DataFee, _ := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config.ChainID, signer, state) + l1DataFee, _ := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config, signer, state, header.Number) result, _ := core.ApplyMessage(vmenv, msg, gp, l1DataFee) if state.Error() == nil { res = append(res, result.Return()...) diff --git a/les/state_accessor.go b/les/state_accessor.go index 80cfbac936f8..9378aefff110 100644 --- a/les/state_accessor.go +++ b/les/state_accessor.go @@ -65,7 +65,7 @@ func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types. } // Not yet the searched for transaction, execute on top of the current state vmenv := vm.NewEVM(context, txContext, statedb, leth.blockchain.Config(), vm.Config{}) - l1DataFee, err := fees.CalculateL1DataFee(tx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(tx, statedb, leth.blockchain.Config(), block.Number()) if err != nil { return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) } diff --git a/light/odr_test.go b/light/odr_test.go index 41c6c48901b5..7dd448535a97 100644 --- a/light/odr_test.go +++ b/light/odr_test.go @@ -201,7 +201,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain vmenv := vm.NewEVM(context, txContext, st, config, vm.Config{NoBaseFee: true}) gp := new(core.GasPool).AddGas(math.MaxUint64) signer := types.MakeSigner(config, header.Number) - l1DataFee, _ := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config.ChainID, signer, st) + l1DataFee, _ := fees.EstimateL1DataFeeForMessage(msg, header.BaseFee, config, signer, st, header.Number) result, _ := core.ApplyMessage(vmenv, msg, gp, l1DataFee) res = append(res, result.Return()...) if st.Error() != nil { diff --git a/light/txpool.go b/light/txpool.go index d6b697fcbe9b..ca3158a78dc9 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -72,6 +72,8 @@ type TxPool struct { istanbul bool // Fork indicator whether we are in the istanbul stage. eip2718 bool // Fork indicator whether we are in the eip2718 stage. shanghai bool // Fork indicator whether we are in the shanghai stage. + + currentHead *big.Int // Current blockchain head } // TxRelayBackend provides an interface to the mechanism that forwards transacions @@ -79,10 +81,13 @@ type TxPool struct { // // Send instructs backend to forward new transactions // NewHead notifies backend about a new head after processed by the tx pool, -// including mined and rolled back transactions since the last event +// +// including mined and rolled back transactions since the last event +// // Discard notifies backend about transactions that should be discarded either -// because they have been replaced by a re-send or because they have been mined -// long ago and no rollback is expected +// +// because they have been replaced by a re-send or because they have been mined +// long ago and no rollback is expected type TxRelayBackend interface { Send(txs types.Transactions) NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) @@ -319,6 +324,8 @@ func (pool *TxPool) setNewHead(head *types.Header) { pool.istanbul = pool.config.IsIstanbul(next) pool.eip2718 = pool.config.IsBerlin(next) pool.shanghai = pool.config.IsShanghai(next) + + pool.currentHead = next } // Stop stops the light transaction pool @@ -387,7 +394,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error // 2. If FeeVault is enabled, perform an additional check for L1 data fees. if pool.config.Scroll.FeeVaultEnabled() { // Get L1 data fee in current state - l1DataFee, err := fees.CalculateL1DataFee(tx, currentState) + l1DataFee, err := fees.CalculateL1DataFee(tx, currentState, pool.config, pool.currentHead) if err != nil { return fmt.Errorf("failed to calculate L1 data fee, err: %w", err) } diff --git a/miner/scroll_worker.go b/miner/scroll_worker.go index bb8da0658c22..3982396e2373 100644 --- a/miner/scroll_worker.go +++ b/miner/scroll_worker.go @@ -461,6 +461,32 @@ func (w *worker) startNewPipeline(timestamp int64) { return } + // Apply special state transition at Curie block + if w.chainConfig.CurieBlock != nil && w.chainConfig.CurieBlock.Cmp(header.Number) == 0 { + misc.ApplyCurieHardFork(parentState) + + // zkEVM requirement: Curie transition block contains 0 transactions, bypass pipeline. + err = w.commit(&pipeline.Result{ + // Note: Signer nodes will not store CCC results for empty blocks in their database. + // In practice, this is acceptable, since this block will never overflow, and follower + // nodes will still store CCC results. + Rows: &types.RowConsumption{}, + FinalBlock: &pipeline.BlockCandidate{ + Header: header, + State: parentState, + Txs: types.Transactions{}, + Receipts: types.Receipts{}, + CoalescedLogs: []*types.Log{}, + }, + }) + + if err != nil { + log.Error("failed to commit Curie fork block", "reason", err) + } + + return + } + // fetch l1Txs var l1Messages []types.L1MessageTx if w.chainConfig.Scroll.ShouldIncludeL1Messages() { diff --git a/miner/worker.go b/miner/worker.go index 40292c3d1d8d..7cef7e3e5c02 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1411,6 +1411,13 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) if w.chainConfig.DAOForkSupport && w.chainConfig.DAOForkBlock != nil && w.chainConfig.DAOForkBlock.Cmp(header.Number) == 0 { misc.ApplyDAOHardFork(env.state) } + if w.chainConfig.CurieBlock != nil && w.chainConfig.CurieBlock.Cmp(header.Number) == 0 { + misc.ApplyCurieHardFork(env.state) + + // zkEVM requirement: Curie transition block has 0 transactions + w.commit(nil, w.fullTaskHook, true, tstart) + return + } // Accumulate the uncles for the current block uncles := make([]*types.Header, 0, 2) commitUncles := func(blocks map[common.Hash]*types.Block) { diff --git a/params/version.go b/params/version.go index 326c7b339ce4..3b8faf29d972 100644 --- a/params/version.go +++ b/params/version.go @@ -24,7 +24,7 @@ import ( const ( VersionMajor = 5 // Major version component of the current release VersionMinor = 3 // Minor version component of the current release - VersionPatch = 26 // Patch version component of the current release + VersionPatch = 27 // Patch version component of the current release VersionMeta = "mainnet" // Version metadata to append to the version string ) diff --git a/rollup/fees/rollup_fee.go b/rollup/fees/rollup_fee.go index 312471a1af6a..7eb110939420 100644 --- a/rollup/fees/rollup_fee.go +++ b/rollup/fees/rollup_fee.go @@ -43,12 +43,21 @@ type StateDB interface { GetBalance(addr common.Address) *big.Int } -func EstimateL1DataFeeForMessage(msg Message, baseFee, chainID *big.Int, signer types.Signer, state StateDB) (*big.Int, error) { +type gpoState struct { + l1BaseFee *big.Int + overhead *big.Int + scalar *big.Int + l1BlobBaseFee *big.Int + commitScalar *big.Int + blobScalar *big.Int +} + +func EstimateL1DataFeeForMessage(msg Message, baseFee *big.Int, config *params.ChainConfig, signer types.Signer, state StateDB, blockNumber *big.Int) (*big.Int, error) { if msg.IsL1MessageTx() { return big.NewInt(0), nil } - unsigned := asUnsignedTx(msg, baseFee, chainID) + unsigned := asUnsignedTx(msg, baseFee, config.ChainID) // with v=1 tx, err := unsigned.WithSignature(signer, append(bytes.Repeat([]byte{0xff}, crypto.SignatureLength-1), 0x01)) if err != nil { @@ -60,8 +69,16 @@ func EstimateL1DataFeeForMessage(msg Message, baseFee, chainID *big.Int, signer return nil, err } - l1BaseFee, overhead, scalar := readGPOStorageSlots(rcfg.L1GasPriceOracleAddress, state) - l1DataFee := calculateEncodedL1DataFee(raw, overhead, l1BaseFee, scalar) + gpoState := readGPOStorageSlots(rcfg.L1GasPriceOracleAddress, state) + + var l1DataFee *big.Int + + if !config.IsCurie(blockNumber) { + l1DataFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) + } else { + l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) + } + return l1DataFee, nil } @@ -126,25 +143,46 @@ func rlpEncode(tx *types.Transaction) ([]byte, error) { return raw.Bytes(), nil } -func readGPOStorageSlots(addr common.Address, state StateDB) (*big.Int, *big.Int, *big.Int) { - l1BaseFee := state.GetState(addr, rcfg.L1BaseFeeSlot) - overhead := state.GetState(addr, rcfg.OverheadSlot) - scalar := state.GetState(addr, rcfg.ScalarSlot) - return l1BaseFee.Big(), overhead.Big(), scalar.Big() +func readGPOStorageSlots(addr common.Address, state StateDB) gpoState { + var gpoState gpoState + gpoState.l1BaseFee = state.GetState(addr, rcfg.L1BaseFeeSlot).Big() + gpoState.overhead = state.GetState(addr, rcfg.OverheadSlot).Big() + gpoState.scalar = state.GetState(addr, rcfg.ScalarSlot).Big() + gpoState.l1BlobBaseFee = state.GetState(addr, rcfg.L1BlobBaseFeeSlot).Big() + gpoState.commitScalar = state.GetState(addr, rcfg.CommitScalarSlot).Big() + gpoState.blobScalar = state.GetState(addr, rcfg.BlobScalarSlot).Big() + return gpoState } // calculateEncodedL1DataFee computes the L1 fee for an RLP-encoded tx -func calculateEncodedL1DataFee(data []byte, overhead, l1GasPrice *big.Int, scalar *big.Int) *big.Int { - l1GasUsed := CalculateL1GasUsed(data, overhead) - l1DataFee := new(big.Int).Mul(l1GasUsed, l1GasPrice) +func calculateEncodedL1DataFee(data []byte, overhead, l1BaseFee *big.Int, scalar *big.Int) *big.Int { + l1GasUsed := calculateL1GasUsed(data, overhead) + l1DataFee := new(big.Int).Mul(l1GasUsed, l1BaseFee) return mulAndScale(l1DataFee, scalar, rcfg.Precision) } -// CalculateL1GasUsed computes the L1 gas used based on the calldata and +// calculateEncodedL1DataFeeCurie computes the L1 fee for an RLP-encoded tx, post Curie +func calculateEncodedL1DataFeeCurie(data []byte, l1BaseFee *big.Int, l1BlobBaseFee *big.Int, commitScalar *big.Int, blobScalar *big.Int) *big.Int { + // calldata component of commit fees (calldata gas + execution) + calldataGas := new(big.Int).Mul(commitScalar, l1BaseFee) + + // blob component of commit fees + blobGas := big.NewInt(int64(len(data))) + blobGas = new(big.Int).Mul(blobGas, l1BlobBaseFee) + blobGas = new(big.Int).Mul(blobGas, blobScalar) + + // combined + l1DataFee := new(big.Int).Add(calldataGas, blobGas) + l1DataFee = new(big.Int).Quo(l1DataFee, rcfg.Precision) + + return l1DataFee +} + +// calculateL1GasUsed computes the L1 gas used based on the calldata and // constant sized overhead. The overhead can be decreased as the cost of the // batch submission goes down via contract optimizations. This will not overflow // under standard network conditions. -func CalculateL1GasUsed(data []byte, overhead *big.Int) *big.Int { +func calculateL1GasUsed(data []byte, overhead *big.Int) *big.Int { zeroes, ones := zeroesAndOnes(data) zeroesGas := zeroes * params.TxDataZeroGas onesGas := (ones + txExtraDataBytes) * params.TxDataNonZeroGasEIP2028 @@ -173,7 +211,7 @@ func mulAndScale(x *big.Int, y *big.Int, precision *big.Int) *big.Int { return new(big.Int).Quo(z, precision) } -func CalculateL1DataFee(tx *types.Transaction, state StateDB) (*big.Int, error) { +func CalculateL1DataFee(tx *types.Transaction, state StateDB, config *params.ChainConfig, blockNumber *big.Int) (*big.Int, error) { if tx.IsL1MessageTx() { return big.NewInt(0), nil } @@ -183,8 +221,16 @@ func CalculateL1DataFee(tx *types.Transaction, state StateDB) (*big.Int, error) return nil, err } - l1BaseFee, overhead, scalar := readGPOStorageSlots(rcfg.L1GasPriceOracleAddress, state) - l1DataFee := calculateEncodedL1DataFee(raw, overhead, l1BaseFee, scalar) + gpoState := readGPOStorageSlots(rcfg.L1GasPriceOracleAddress, state) + + var l1DataFee *big.Int + + if !config.IsCurie(blockNumber) { + l1DataFee = calculateEncodedL1DataFee(raw, gpoState.overhead, gpoState.l1BaseFee, gpoState.scalar) + } else { + l1DataFee = calculateEncodedL1DataFeeCurie(raw, gpoState.l1BaseFee, gpoState.l1BlobBaseFee, gpoState.commitScalar, gpoState.blobScalar) + } + return l1DataFee, nil } diff --git a/rollup/fees/rollup_fee_test.go b/rollup/fees/rollup_fee_test.go index 54b77eeb151c..b35d8cd9bf55 100644 --- a/rollup/fees/rollup_fee_test.go +++ b/rollup/fees/rollup_fee_test.go @@ -7,14 +7,27 @@ import ( "github.com/stretchr/testify/assert" ) -func TestCalculateEncodedL1DataFee(t *testing.T) { +func TestL1DataFeeBeforeCurie(t *testing.T) { l1BaseFee := new(big.Int).SetUint64(15000000) - - data := []byte{0, 10, 1, 0} overhead := new(big.Int).SetUint64(100) scalar := new(big.Int).SetUint64(10) - expected := new(big.Int).SetUint64(184) // 184.2 + data := []byte{0, 10, 1, 0} + + expected := new(big.Int).SetUint64(30) // 30.6 actual := calculateEncodedL1DataFee(data, overhead, l1BaseFee, scalar) assert.Equal(t, expected, actual) } + +func TestL1DataFeeAfterCurie(t *testing.T) { + l1BaseFee := new(big.Int).SetUint64(1500000000) + l1BlobBaseFee := new(big.Int).SetUint64(150000000) + commitScalar := new(big.Int).SetUint64(10) + blobScalar := new(big.Int).SetUint64(10) + + data := []byte{0, 10, 1, 0} + + expected := new(big.Int).SetUint64(21) + actual := calculateEncodedL1DataFeeCurie(data, l1BaseFee, l1BlobBaseFee, commitScalar, blobScalar) + assert.Equal(t, expected, actual) +} diff --git a/rollup/pipeline/pipeline.go b/rollup/pipeline/pipeline.go index 3c7089cf60e5..0cfad6ad5759 100644 --- a/rollup/pipeline/pipeline.go +++ b/rollup/pipeline/pipeline.go @@ -51,7 +51,7 @@ type Pipeline struct { parent *types.Block start time.Time - // accumalators + // accumulators ccc *circuitcapacitychecker.CircuitCapacityChecker Header types.Header state *state.StateDB diff --git a/rollup/rcfg/config.go b/rollup/rcfg/config.go index 3e0e00ce041e..005ca7d08833 100644 --- a/rollup/rcfg/config.go +++ b/rollup/rcfg/config.go @@ -29,4 +29,23 @@ var ( L1BaseFeeSlot = common.BigToHash(big.NewInt(1)) OverheadSlot = common.BigToHash(big.NewInt(2)) ScalarSlot = common.BigToHash(big.NewInt(3)) + + // New fields added in the Curie hard fork + L1BlobBaseFeeSlot = common.BigToHash(big.NewInt(5)) + CommitScalarSlot = common.BigToHash(big.NewInt(6)) + BlobScalarSlot = common.BigToHash(big.NewInt(7)) + IsCurieSlot = common.BigToHash(big.NewInt(8)) + + InitialCommitScalar = big.NewInt(230759955285) + InitialBlobScalar = big.NewInt(417565260) + + // CurieL1GasPriceOracleBytecode is the new (blob-enabled) gas price oracle after + // the Curie hard fork. Run these commands in the monorepo to verify this bytecode: + // + // git checkout 7059ad0ed465201287e06625dd4058c8ae9682b8 + // cd contracts + // yarn + // FOUNDRY_EVM_VERSION="cancun" forge build + // cat artifacts/src/L1GasPriceOracle.sol/L1GasPriceOracle.json | jq -r .deployedBytecode.object + CurieL1GasPriceOracleBytecode = common.Hex2Bytes("608060405234801561000f575f80fd5b5060043610610132575f3560e01c8063715018a6116100b4578063a911d77f11610079578063a911d77f1461024c578063bede39b514610254578063de26c4a114610267578063e88a60ad1461027a578063f2fde38b1461028d578063f45e65d8146102a0575f80fd5b8063715018a6146101eb57806384189161146101f35780638da5cb5b146101fc57806393e59dc114610226578063944b247f14610239575f80fd5b80633d0f963e116100fa5780633d0f963e146101a057806349948e0e146101b3578063519b4bd3146101c65780636a5e67e5146101cf57806370465597146101d8575f80fd5b80630c18c1621461013657806313dad5be1461015257806323e524ac1461016f5780633577afc51461017857806339455d3a1461018d575b5f80fd5b61013f60025481565b6040519081526020015b60405180910390f35b60085461015f9060ff1681565b6040519015158152602001610149565b61013f60065481565b61018b6101863660046109c3565b6102a9565b005b61018b61019b3660046109da565b61033b565b61018b6101ae3660046109fa565b610438565b61013f6101c1366004610a3b565b6104bb565b61013f60015481565b61013f60075481565b61018b6101e63660046109c3565b6104e0565b61018b61056e565b61013f60055481565b5f5461020e906001600160a01b031681565b6040516001600160a01b039091168152602001610149565b60045461020e906001600160a01b031681565b61018b6102473660046109c3565b6105a2565b61018b610636565b61018b6102623660046109c3565b610692565b61013f610275366004610a3b565b61074f565b61018b6102883660046109c3565b61076c565b61018b61029b3660046109fa565b610800565b61013f60035481565b5f546001600160a01b031633146102db5760405162461bcd60e51b81526004016102d290610ae6565b60405180910390fd5b621c9c388111156102ff57604051635742c80560e11b815260040160405180910390fd5b60028190556040518181527f32740b35c0ea213650f60d44366b4fb211c9033b50714e4a1d34e65d5beb9bb4906020015b60405180910390a150565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa158015610382573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a69190610b1d565b6103c3576040516326b3506d60e11b815260040160405180910390fd5b600182905560058190556040518281527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c449060200160405180910390a16040518181527f9a14bfb5d18c4c3cf14cae19c23d7cf1bcede357ea40ca1f75cd49542c71c214906020015b60405180910390a15050565b5f546001600160a01b031633146104615760405162461bcd60e51b81526004016102d290610ae6565b600480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f22d1c35fe072d2e42c3c8f9bd4a0d34aa84a0101d020a62517b33fdb3174e5f7910161042c565b6008545f9060ff16156104d7576104d18261088b565b92915050565b6104d1826108d1565b5f546001600160a01b031633146105095760405162461bcd60e51b81526004016102d290610ae6565b610519633b9aca006103e8610b50565b81111561053957604051631e44fdeb60e11b815260040160405180910390fd5b60038190556040518181527f3336cd9708eaf2769a0f0dc0679f30e80f15dcd88d1921b5a16858e8b85c591a90602001610330565b5f546001600160a01b031633146105975760405162461bcd60e51b81526004016102d290610ae6565b6105a05f610914565b565b5f546001600160a01b031633146105cb5760405162461bcd60e51b81526004016102d290610ae6565b6105e1633b9aca00670de0b6b3a7640000610b50565b8111156106015760405163874f603160e01b815260040160405180910390fd5b60068190556040518181527f2ab3f5a4ebbcbf3c24f62f5454f52f10e1a8c9dcc5acac8f19199ce881a6a10890602001610330565b5f546001600160a01b0316331461065f5760405162461bcd60e51b81526004016102d290610ae6565b60085460ff1615610683576040516379f9c57560e01b815260040160405180910390fd5b6008805460ff19166001179055565b6004805460405163efc7840160e01b815233928101929092526001600160a01b03169063efc7840190602401602060405180830381865afa1580156106d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106fd9190610b1d565b61071a576040516326b3506d60e11b815260040160405180910390fd5b60018190556040518181527f351fb23757bb5ea0546c85b7996ddd7155f96b939ebaa5ff7bc49c75f27f2c4490602001610330565b6008545f9060ff161561076357505f919050565b6104d182610963565b5f546001600160a01b031633146107955760405162461bcd60e51b81526004016102d290610ae6565b6107ab633b9aca00670de0b6b3a7640000610b50565b8111156107cb5760405163f37ec21560e01b815260040160405180910390fd5b60078190556040518181527f6b332a036d8c3ead57dcb06c87243bd7a2aed015ddf2d0528c2501dae56331aa90602001610330565b5f546001600160a01b031633146108295760405162461bcd60e51b81526004016102d290610ae6565b6001600160a01b03811661087f5760405162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f206164647265737300000060448201526064016102d2565b61088881610914565b50565b5f633b9aca0060055483516007546108a39190610b50565b6108ad9190610b50565b6001546006546108bd9190610b50565b6108c79190610b67565b6104d19190610b7a565b5f806108dc83610963565b90505f600154826108ed9190610b50565b9050633b9aca00600354826109029190610b50565b61090c9190610b7a565b949350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80515f908190815b818110156109b45784818151811061098557610985610b99565b01602001516001600160f81b0319165f036109a5576004830192506109ac565b6010830192505b60010161096b565b50506002540160400192915050565b5f602082840312156109d3575f80fd5b5035919050565b5f80604083850312156109eb575f80fd5b50508035926020909101359150565b5f60208284031215610a0a575f80fd5b81356001600160a01b0381168114610a20575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610a4b575f80fd5b813567ffffffffffffffff80821115610a62575f80fd5b818401915084601f830112610a75575f80fd5b813581811115610a8757610a87610a27565b604051601f8201601f19908116603f01168101908382118183101715610aaf57610aaf610a27565b81604052828152876020848701011115610ac7575f80fd5b826020860160208301375f928101602001929092525095945050505050565b60208082526017908201527f63616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b5f60208284031215610b2d575f80fd5b81518015158114610a20575f80fd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176104d1576104d1610b3c565b808201808211156104d1576104d1610b3c565b5f82610b9457634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffdfea26469706673582212206579d545ea4839464c2fd4ba9a7e6a4f4fee1cc1b51182da675c0f0c05fc161964736f6c63430008180033") ) diff --git a/rollup/tracing/tracing.go b/rollup/tracing/tracing.go index 321b3885ecc9..f83e419c64ae 100644 --- a/rollup/tracing/tracing.go +++ b/rollup/tracing/tracing.go @@ -229,7 +229,7 @@ func (env *TraceEnv) GetBlockTrace(block *types.Block) (*types.BlockTrace, error msg, _ := tx.AsMessage(env.signer, block.BaseFee()) env.state.SetTxContext(tx.Hash(), i) vmenv := vm.NewEVM(env.blockCtx, core.NewEVMTxContext(msg), env.state, env.chainConfig, vm.Config{}) - l1DataFee, err := fees.CalculateL1DataFee(tx, env.state) + l1DataFee, err := fees.CalculateL1DataFee(tx, env.state, env.chainConfig, block.Number()) if err != nil { failed = err break @@ -335,7 +335,7 @@ func (env *TraceEnv) getTxResult(state *state.StateDB, index int, block *types.B state.SetTxContext(txctx.TxHash, txctx.TxIndex) // Computes the new state by applying the given message. - l1DataFee, err := fees.CalculateL1DataFee(tx, state) + l1DataFee, err := fees.CalculateL1DataFee(tx, state, env.chainConfig, block.Number()) if err != nil { return err } @@ -530,6 +530,10 @@ func (env *TraceEnv) fillBlockTrace(block *types.Block) (*types.BlockTrace, erro rcfg.L1BaseFeeSlot, rcfg.OverheadSlot, rcfg.ScalarSlot, + rcfg.L1BlobBaseFeeSlot, + rcfg.CommitScalarSlot, + rcfg.BlobScalarSlot, + rcfg.IsCurieSlot, }, } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 01ff828b8817..959c513d05c7 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -227,7 +227,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh gaspool := new(core.GasPool) gaspool.AddGas(block.GasLimit()) - l1DataFee, err := fees.CalculateL1DataFee(&ttx, statedb) + l1DataFee, err := fees.CalculateL1DataFee(&ttx, statedb, config, block.Number()) if err != nil { return nil, nil, common.Hash{}, err }