Commit 2f295d03 authored by protolambda's avatar protolambda Committed by GitHub

devnet/e2e: run L1 Deneb and L2 Fjord by default (#11359)

* devnet/e2e: run L1 Deneb and L2 Fjord by default

* op-e2e: fix TestPostUnsafePayload

* op-e2e: Fix TestGasPriceOracleFeeUpdates

* op-e2e/actions: fix some tests

The L2EngineAPI test needs more fixing

* tests: fixes to support Ecotone/Fjord in more tests

* op-e2e: one more fix

---------
Co-authored-by: default avatarSebastian Stammler <seb@oplabs.co>
parent b047e1fd
...@@ -62,8 +62,7 @@ func TestDencunL1ForkAfterGenesis(gt *testing.T) { ...@@ -62,8 +62,7 @@ func TestDencunL1ForkAfterGenesis(gt *testing.T) {
func TestDencunL1ForkAtGenesis(gt *testing.T) { func TestDencunL1ForkAtGenesis(gt *testing.T) {
t := NewDefaultTesting(gt) t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
offset := hexutil.Uint64(0) require.Zero(t, *dp.DeployConfig.L1CancunTimeOffset)
dp.DeployConfig.L1CancunTimeOffset = &offset
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LevelDebug) log := testlog.Logger(t, log.LevelDebug)
_, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log)
...@@ -120,14 +119,13 @@ func verifyEcotoneBlock(gt *testing.T, header *types.Header) { ...@@ -120,14 +119,13 @@ func verifyEcotoneBlock(gt *testing.T, header *types.Header) {
func TestDencunL2ForkAfterGenesis(gt *testing.T) { func TestDencunL2ForkAfterGenesis(gt *testing.T) {
t := NewDefaultTesting(gt) t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
require.Zero(t, *dp.DeployConfig.L1CancunTimeOffset)
cancunOffset := hexutil.Uint64(0)
dp.DeployConfig.L1CancunTimeOffset = &cancunOffset
// This test wil fork on the second block // This test wil fork on the second block
offset := hexutil.Uint64(dp.DeployConfig.L2BlockTime * 2) offset := hexutil.Uint64(dp.DeployConfig.L2BlockTime * 2)
dp.DeployConfig.L2GenesisCanyonTimeOffset = &offset
dp.DeployConfig.L2GenesisDeltaTimeOffset = &offset
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset
dp.DeployConfig.L2GenesisFjordTimeOffset = nil
dp.DeployConfig.L2GenesisGraniteTimeOffset = nil
// New forks have to be added here, after changing the default deploy config!
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LevelDebug) log := testlog.Logger(t, log.LevelDebug)
...@@ -159,12 +157,7 @@ func TestDencunL2ForkAfterGenesis(gt *testing.T) { ...@@ -159,12 +157,7 @@ func TestDencunL2ForkAfterGenesis(gt *testing.T) {
func TestDencunL2ForkAtGenesis(gt *testing.T) { func TestDencunL2ForkAtGenesis(gt *testing.T) {
t := NewDefaultTesting(gt) t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
offset := hexutil.Uint64(0) require.Zero(t, *dp.DeployConfig.L2GenesisEcotoneTimeOffset)
dp.DeployConfig.L2GenesisRegolithTimeOffset = &offset
dp.DeployConfig.L1CancunTimeOffset = &offset
dp.DeployConfig.L2GenesisCanyonTimeOffset = &offset
dp.DeployConfig.L2GenesisDeltaTimeOffset = &offset
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LevelDebug) log := testlog.Logger(t, log.LevelDebug)
...@@ -202,11 +195,6 @@ func newEngine(t Testing, sd *e2eutils.SetupData, log log.Logger) *L2Engine { ...@@ -202,11 +195,6 @@ func newEngine(t Testing, sd *e2eutils.SetupData, log log.Logger) *L2Engine {
func TestDencunBlobTxRPC(gt *testing.T) { func TestDencunBlobTxRPC(gt *testing.T) {
t := NewDefaultTesting(gt) t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
offset := hexutil.Uint64(0)
dp.DeployConfig.L2GenesisRegolithTimeOffset = &offset
dp.DeployConfig.L2GenesisCanyonTimeOffset = &offset
dp.DeployConfig.L2GenesisDeltaTimeOffset = &offset
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LevelDebug) log := testlog.Logger(t, log.LevelDebug)
...@@ -221,11 +209,6 @@ func TestDencunBlobTxRPC(gt *testing.T) { ...@@ -221,11 +209,6 @@ func TestDencunBlobTxRPC(gt *testing.T) {
func TestDencunBlobTxInTxPool(gt *testing.T) { func TestDencunBlobTxInTxPool(gt *testing.T) {
t := NewDefaultTesting(gt) t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
offset := hexutil.Uint64(0)
dp.DeployConfig.L2GenesisRegolithTimeOffset = &offset
dp.DeployConfig.L2GenesisCanyonTimeOffset = &offset
dp.DeployConfig.L2GenesisDeltaTimeOffset = &offset
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LevelDebug) log := testlog.Logger(t, log.LevelDebug)
...@@ -239,11 +222,6 @@ func TestDencunBlobTxInTxPool(gt *testing.T) { ...@@ -239,11 +222,6 @@ func TestDencunBlobTxInTxPool(gt *testing.T) {
func TestDencunBlobTxInclusion(gt *testing.T) { func TestDencunBlobTxInclusion(gt *testing.T) {
t := NewDefaultTesting(gt) t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
offset := hexutil.Uint64(0)
dp.DeployConfig.L2GenesisRegolithTimeOffset = &offset
dp.DeployConfig.L2GenesisCanyonTimeOffset = &offset
dp.DeployConfig.L2GenesisDeltaTimeOffset = &offset
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LevelDebug) log := testlog.Logger(t, log.LevelDebug)
......
...@@ -42,18 +42,16 @@ func verifyCodeHashMatches(t Testing, client *ethclient.Client, address common.A ...@@ -42,18 +42,16 @@ func verifyCodeHashMatches(t Testing, client *ethclient.Client, address common.A
func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) {
t := NewDefaultTesting(gt) t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
genesisBlock := hexutil.Uint64(0)
ecotoneOffset := hexutil.Uint64(4) ecotoneOffset := hexutil.Uint64(4)
log := testlog.Logger(t, log.LevelDebug) log := testlog.Logger(t, log.LevelDebug)
dp.DeployConfig.L1CancunTimeOffset = &genesisBlock // can be removed once Cancun on L1 is the default require.Zero(t, *dp.DeployConfig.L1CancunTimeOffset)
// Activate all forks at genesis, and schedule Ecotone the block after // Activate all forks at genesis, and schedule Ecotone the block after
dp.DeployConfig.L2GenesisRegolithTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &ecotoneOffset dp.DeployConfig.L2GenesisEcotoneTimeOffset = &ecotoneOffset
dp.DeployConfig.L2GenesisFjordTimeOffset = nil
dp.DeployConfig.L2GenesisGraniteTimeOffset = nil
// New forks have to be added here...
require.NoError(t, dp.DeployConfig.Check(log), "must have valid config") require.NoError(t, dp.DeployConfig.Check(log), "must have valid config")
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
......
package actions package actions
import ( import (
"encoding/binary"
"errors" "errors"
"math/big" "math/big"
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi" "github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi/test"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb"
"github.com/ethereum/go-ethereum/triedb/hashdb" "github.com/ethereum/go-ethereum/triedb/hashdb"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi/test"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testlog"
...@@ -44,50 +46,62 @@ func TestL2EngineAPI(gt *testing.T) { ...@@ -44,50 +46,62 @@ func TestL2EngineAPI(gt *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// build an empty block // build an empty block
chainA, _ := core.GenerateChain(sd.L2Cfg.Config, genesisBlock, consensus, db, 1, func(i int, gen *core.BlockGen) { chainA, _ := core.GenerateChain(sd.L2Cfg.Config, genesisBlock, consensus, db, 1, func(n int, gen *core.BlockGen) {
gen.SetCoinbase(common.Address{'A'}) gen.SetCoinbase(common.Address{'A'})
if sd.L2Cfg.Config.IsCancun(gen.Number(), gen.Timestamp()) {
root := crypto.Keccak256Hash([]byte("A"), binary.BigEndian.AppendUint64(nil, uint64(n)))
gen.SetParentBeaconRoot(root)
}
}) })
payloadA, err := eth.BlockAsPayload(chainA[0], sd.RollupCfg.CanyonTime)
payloadA, err := eth.BlockAsPayloadEnv(chainA[0], sd.RollupCfg.CanyonTime)
require.NoError(t, err) require.NoError(t, err)
// apply the payload // apply the payload
status, err := l2Cl.NewPayload(t.Ctx(), payloadA, nil) status, err := l2Cl.NewPayload(t.Ctx(), payloadA.ExecutionPayload, payloadA.ParentBeaconBlockRoot)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, status.Status, eth.ExecutionValid) require.Equal(t, eth.ExecutionValid, status.Status)
require.Equal(t, genesisBlock.Hash(), engine.l2Chain.CurrentBlock().Hash(), "processed payloads are not immediately canonical") require.Equal(t, genesisBlock.Hash(), engine.l2Chain.CurrentBlock().Hash(), "processed payloads are not immediately canonical")
// recognize the payload as canonical // recognize the payload as canonical
fcRes, err := l2Cl.ForkchoiceUpdate(t.Ctx(), &eth.ForkchoiceState{ fcRes, err := l2Cl.ForkchoiceUpdate(t.Ctx(), &eth.ForkchoiceState{
HeadBlockHash: payloadA.BlockHash, HeadBlockHash: payloadA.ExecutionPayload.BlockHash,
SafeBlockHash: genesisBlock.Hash(), SafeBlockHash: genesisBlock.Hash(),
FinalizedBlockHash: genesisBlock.Hash(), FinalizedBlockHash: genesisBlock.Hash(),
}, nil) }, nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, fcRes.PayloadStatus.Status, eth.ExecutionValid) require.Equal(t, fcRes.PayloadStatus.Status, eth.ExecutionValid)
require.Equal(t, payloadA.BlockHash, engine.l2Chain.CurrentBlock().Hash(), "now payload A is canonical") require.Equal(t, payloadA.ExecutionPayload.BlockHash, engine.l2Chain.CurrentBlock().Hash(), "now payload A is canonical")
// build an alternative block // build an alternative block
chainB, _ := core.GenerateChain(sd.L2Cfg.Config, genesisBlock, consensus, db, 1, func(i int, gen *core.BlockGen) { chainB, _ := core.GenerateChain(sd.L2Cfg.Config, genesisBlock, consensus, db, 1, func(n int, gen *core.BlockGen) {
gen.SetCoinbase(common.Address{'B'}) gen.SetCoinbase(common.Address{'B'})
if sd.L2Cfg.Config.IsCancun(gen.Number(), gen.Timestamp()) {
root := crypto.Keccak256Hash([]byte("A"), binary.BigEndian.AppendUint64(nil, uint64(n)))
gen.SetParentBeaconRoot(root)
}
}) })
payloadB, err := eth.BlockAsPayload(chainB[0], sd.RollupCfg.CanyonTime)
payloadB, err := eth.BlockAsPayloadEnv(chainB[0], sd.RollupCfg.CanyonTime)
require.NoError(t, err) require.NoError(t, err)
// apply the payload // apply the payload
status, err = l2Cl.NewPayload(t.Ctx(), payloadB, nil) status, err = l2Cl.NewPayload(t.Ctx(), payloadB.ExecutionPayload, payloadB.ParentBeaconBlockRoot)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, status.Status, eth.ExecutionValid) require.Equal(t, status.Status, eth.ExecutionValid)
require.Equal(t, payloadA.BlockHash, engine.l2Chain.CurrentBlock().Hash(), "processed payloads are not immediately canonical") require.Equal(t, payloadA.ExecutionPayload.BlockHash, engine.l2Chain.CurrentBlock().Hash(), "processed payloads are not immediately canonical")
// reorg block A in favor of block B // reorg block A in favor of block B
fcRes, err = l2Cl.ForkchoiceUpdate(t.Ctx(), &eth.ForkchoiceState{ fcRes, err = l2Cl.ForkchoiceUpdate(t.Ctx(), &eth.ForkchoiceState{
HeadBlockHash: payloadB.BlockHash, HeadBlockHash: payloadB.ExecutionPayload.BlockHash,
SafeBlockHash: genesisBlock.Hash(), SafeBlockHash: genesisBlock.Hash(),
FinalizedBlockHash: genesisBlock.Hash(), FinalizedBlockHash: genesisBlock.Hash(),
}, nil) }, nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, fcRes.PayloadStatus.Status, eth.ExecutionValid) require.Equal(t, fcRes.PayloadStatus.Status, eth.ExecutionValid)
require.Equal(t, payloadB.BlockHash, engine.l2Chain.CurrentBlock().Hash(), "now payload B is canonical") require.Equal(t, payloadB.ExecutionPayload.BlockHash, engine.l2Chain.CurrentBlock().Hash(), "now payload B is canonical")
} }
func TestL2EngineAPIBlockBuilding(gt *testing.T) { func TestL2EngineAPIBlockBuilding(gt *testing.T) {
...@@ -133,6 +147,11 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) { ...@@ -133,6 +147,11 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) {
w = &types.Withdrawals{} w = &types.Withdrawals{}
} }
var parentBeaconBlockRoot *common.Hash
if sd.RollupCfg.IsEcotone(uint64(nextBlockTime)) {
parentBeaconBlockRoot = &common.Hash{}
}
// Now let's ask the engine to build a block // Now let's ask the engine to build a block
fcRes, err := l2Cl.ForkchoiceUpdate(t.Ctx(), &eth.ForkchoiceState{ fcRes, err := l2Cl.ForkchoiceUpdate(t.Ctx(), &eth.ForkchoiceState{
HeadBlockHash: parent.Hash(), HeadBlockHash: parent.Hash(),
...@@ -146,6 +165,7 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) { ...@@ -146,6 +165,7 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) {
NoTxPool: false, NoTxPool: false,
GasLimit: (*eth.Uint64Quantity)(&sd.RollupCfg.Genesis.SystemConfig.GasLimit), GasLimit: (*eth.Uint64Quantity)(&sd.RollupCfg.Genesis.SystemConfig.GasLimit),
Withdrawals: w, Withdrawals: w,
ParentBeaconBlockRoot: parentBeaconBlockRoot,
}) })
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, fcRes.PayloadStatus.Status, eth.ExecutionValid) require.Equal(t, fcRes.PayloadStatus.Status, eth.ExecutionValid)
...@@ -161,7 +181,7 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) { ...@@ -161,7 +181,7 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) {
require.Equal(t, parent.Hash(), payload.ParentHash, "block builds on parent block") require.Equal(t, parent.Hash(), payload.ParentHash, "block builds on parent block")
// apply the payload // apply the payload
status, err := l2Cl.NewPayload(t.Ctx(), payload, nil) status, err := l2Cl.NewPayload(t.Ctx(), payload, envelope.ParentBeaconBlockRoot)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, status.Status, eth.ExecutionValid) require.Equal(t, status.Status, eth.ExecutionValid)
require.Equal(t, parent.Hash(), engine.l2Chain.CurrentBlock().Hash(), "processed payloads are not immediately canonical") require.Equal(t, parent.Hash(), engine.l2Chain.CurrentBlock().Hash(), "processed payloads are not immediately canonical")
......
...@@ -132,6 +132,11 @@ func TestHardforkMiddleOfSpanBatch(gt *testing.T) { ...@@ -132,6 +132,11 @@ func TestHardforkMiddleOfSpanBatch(gt *testing.T) {
// Activate HF in the middle of the first epoch // Activate HF in the middle of the first epoch
deltaOffset := hexutil.Uint64(6) deltaOffset := hexutil.Uint64(6)
applyDeltaTimeOffset(dp, &deltaOffset) applyDeltaTimeOffset(dp, &deltaOffset)
// Applies to HF that goes into Delta. Otherwise we end up with more upgrade txs and things during this case.
dp.DeployConfig.L2GenesisEcotoneTimeOffset = nil
dp.DeployConfig.L2GenesisFjordTimeOffset = nil
dp.DeployConfig.L2GenesisGraniteTimeOffset = nil
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LevelError) log := testlog.Logger(t, log.LevelError)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
......
...@@ -228,6 +228,14 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -228,6 +228,14 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
t := NewDefaultTesting(gt) t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
applyDeltaTimeOffset(dp, deltaTimeOffset) applyDeltaTimeOffset(dp, deltaTimeOffset)
// activating Delta only, not Ecotone and further:
// the GPO change assertions here all apply only for the Delta transition.
// Separate tests cover Ecotone GPO changes.
dp.DeployConfig.L2GenesisEcotoneTimeOffset = nil
dp.DeployConfig.L2GenesisFjordTimeOffset = nil
dp.DeployConfig.L2GenesisGraniteTimeOffset = nil
sd := e2eutils.Setup(t, dp, defaultAlloc) sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LevelDebug) log := testlog.Logger(t, log.LevelDebug)
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log)
......
...@@ -198,19 +198,19 @@ func TestPostUnsafePayload(t *testing.T) { ...@@ -198,19 +198,19 @@ func TestPostUnsafePayload(t *testing.T) {
blockNumberOne, err := l2Seq.BlockByNumber(ctx, big.NewInt(1)) blockNumberOne, err := l2Seq.BlockByNumber(ctx, big.NewInt(1))
require.NoError(t, err) require.NoError(t, err)
payload, err := eth.BlockAsPayload(blockNumberOne, sys.RollupConfig.CanyonTime) payloadEnv, err := eth.BlockAsPayloadEnv(blockNumberOne, sys.RollupConfig.CanyonTime)
require.NoError(t, err) require.NoError(t, err)
err = rollupClient.PostUnsafePayload(ctx, &eth.ExecutionPayloadEnvelope{ExecutionPayload: payload}) err = rollupClient.PostUnsafePayload(ctx, payloadEnv)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, wait.ForUnsafeBlock(ctx, rollupClient, 1), "Chain did not advance after posting payload") require.NoError(t, wait.ForUnsafeBlock(ctx, rollupClient, 1), "Chain did not advance after posting payload")
// Test validation // Test validation
blockNumberTwo, err := l2Seq.BlockByNumber(ctx, big.NewInt(2)) blockNumberTwo, err := l2Seq.BlockByNumber(ctx, big.NewInt(2))
require.NoError(t, err) require.NoError(t, err)
payload, err = eth.BlockAsPayload(blockNumberTwo, sys.RollupConfig.CanyonTime) payloadEnv, err = eth.BlockAsPayloadEnv(blockNumberTwo, sys.RollupConfig.CanyonTime)
require.NoError(t, err) require.NoError(t, err)
payload.BlockHash = common.Hash{0xaa} payloadEnv.ExecutionPayload.BlockHash = common.Hash{0xaa}
err = rollupClient.PostUnsafePayload(ctx, &eth.ExecutionPayloadEnvelope{ExecutionPayload: payload}) err = rollupClient.PostUnsafePayload(ctx, payloadEnv)
require.ErrorContains(t, err, "payload has bad block hash") require.ErrorContains(t, err, "payload has bad block hash")
} }
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"context" "context"
"crypto/ecdsa" "crypto/ecdsa"
"fmt" "fmt"
"math"
"math/big" "math/big"
"math/rand" "math/rand"
"testing" "testing"
...@@ -19,10 +20,10 @@ import ( ...@@ -19,10 +20,10 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-node/bindings" "github.com/ethereum-optimism/optimism/op-node/bindings"
bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview" bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/predeploys"
"github.com/ethereum-optimism/optimism/op-service/testutils/fuzzerutils" "github.com/ethereum-optimism/optimism/op-service/testutils/fuzzerutils"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
...@@ -41,17 +42,16 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) { ...@@ -41,17 +42,16 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) {
defer ctxCancel() defer ctxCancel()
InitParallel(t) InitParallel(t)
// Define our values to set in the GasPriceOracle (we set them high to see if it can lock L2 or stop bindings maxScalars := eth.EcotoneScalars{
// from updating the prices once again. BaseFeeScalar: math.MaxUint32,
overheadValue := new(big.Int).Set(abi.MaxUint256) BlobBaseFeeScalar: math.MaxUint32,
// Ensure the most significant byte is 0x00 }
scalarValue := new(big.Int).Rsh(new(big.Int).Set(abi.MaxUint256), 8)
var cancel context.CancelFunc var cancel context.CancelFunc
// Create our system configuration for L1/L2 and start it // Create our system configuration for L1/L2 and start it
cfg := DefaultSystemConfig(t) cfg := DefaultSystemConfig(t)
sys, err := cfg.Start(t) sys, err := cfg.Start(t)
require.Nil(t, err, "Error starting up system") require.NoError(t, err, "Error starting up system")
defer sys.Close() defer sys.Close()
// Obtain our sequencer, verifier, and transactor keypair. // Obtain our sequencer, verifier, and transactor keypair.
...@@ -62,66 +62,61 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) { ...@@ -62,66 +62,61 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) {
// Bind to the SystemConfig & GasPriceOracle contracts // Bind to the SystemConfig & GasPriceOracle contracts
sysconfig, err := legacybindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1Client) sysconfig, err := legacybindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1Client)
require.Nil(t, err) require.NoError(t, err)
gpoContract, err := legacybindings.NewGasPriceOracleCaller(predeploys.GasPriceOracleAddr, l2Seq) gpoContract, err := legacybindings.NewGasPriceOracleCaller(predeploys.GasPriceOracleAddr, l2Seq)
require.Nil(t, err) require.NoError(t, err)
// Obtain our signer. // Obtain our signer.
opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig()) opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig())
require.Nil(t, err) require.NoError(t, err)
// Define our L1 transaction timeout duration. // Define our L1 transaction timeout duration.
txTimeoutDuration := 10 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second txTimeoutDuration := 10 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second
// Update the gas config, wait for it to show up on L2, & verify that it was set as intended // Update the gas config, wait for it to show up on L2, & verify that it was set as intended
opts.Context, cancel = context.WithTimeout(ctx, txTimeoutDuration) opts.Context, cancel = context.WithTimeout(ctx, txTimeoutDuration)
tx, err := sysconfig.SetGasConfig(opts, overheadValue, scalarValue) tx, err := sysconfig.SetGasConfigEcotone(opts, maxScalars.BaseFeeScalar, maxScalars.BlobBaseFeeScalar)
cancel() cancel()
require.Nil(t, err, "sending overhead update tx") require.NoError(t, err, "SetGasConfigEcotone update tx")
receipt, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash()) receipt, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash())
require.Nil(t, err, "Waiting for sysconfig set gas config update tx") require.NoError(t, err, "Waiting for sysconfig set gas config update tx")
_, err = geth.WaitForL1OriginOnL2(sys.RollupConfig, receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration) _, err = geth.WaitForL1OriginOnL2(sys.RollupConfig, receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration)
require.NoError(t, err, "waiting for L2 block to include the sysconfig update") require.NoError(t, err, "waiting for L2 block to include the sysconfig update")
gpoOverhead, err := gpoContract.Overhead(&bind.CallOpts{}) baseFeeScalar, err := gpoContract.BaseFeeScalar(&bind.CallOpts{})
require.Nil(t, err, "reading gpo overhead") require.NoError(t, err, "reading base fee scalar")
gpoScalar, err := gpoContract.Scalar(&bind.CallOpts{}) require.Equal(t, baseFeeScalar, maxScalars.BaseFeeScalar)
require.Nil(t, err, "reading gpo scalar")
if gpoOverhead.Cmp(overheadValue) != 0 { blobBaseFeeScalar, err := gpoContract.BlobBaseFeeScalar(&bind.CallOpts{})
t.Errorf("overhead that was found (%v) is not what was set (%v)", gpoOverhead, overheadValue) require.NoError(t, err, "reading blob base fee scalar")
} require.Equal(t, blobBaseFeeScalar, maxScalars.BlobBaseFeeScalar)
if gpoScalar.Cmp(scalarValue) != 0 {
t.Errorf("scalar that was found (%v) is not what was set (%v)", gpoScalar, scalarValue)
}
// Now modify the scalar value & ensure that the gas params can be modified // Now modify the scalar value & ensure that the gas params can be modified
scalarValue = big.NewInt(params.Ether) normalScalars := eth.EcotoneScalars{
BaseFeeScalar: 1e6,
BlobBaseFeeScalar: 1e6,
}
opts.Context, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) opts.Context, cancel = context.WithTimeout(context.Background(), txTimeoutDuration)
tx, err = sysconfig.SetGasConfig(opts, overheadValue, scalarValue) tx, err = sysconfig.SetGasConfigEcotone(opts, normalScalars.BaseFeeScalar, normalScalars.BlobBaseFeeScalar)
cancel() cancel()
require.Nil(t, err, "sending overhead update tx") require.NoError(t, err, "SetGasConfigEcotone update tx")
receipt, err = wait.ForReceiptOK(ctx, l1Client, tx.Hash()) receipt, err = wait.ForReceiptOK(ctx, l1Client, tx.Hash())
require.Nil(t, err, "Waiting for sysconfig set gas config update tx") require.NoError(t, err, "Waiting for sysconfig set gas config update tx")
_, err = geth.WaitForL1OriginOnL2(sys.RollupConfig, receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration) _, err = geth.WaitForL1OriginOnL2(sys.RollupConfig, receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration)
require.NoError(t, err, "waiting for L2 block to include the sysconfig update") require.NoError(t, err, "waiting for L2 block to include the sysconfig update")
gpoOverhead, err = gpoContract.Overhead(&bind.CallOpts{}) baseFeeScalar, err = gpoContract.BaseFeeScalar(&bind.CallOpts{})
require.Nil(t, err, "reading gpo overhead") require.NoError(t, err, "reading base fee scalar")
gpoScalar, err = gpoContract.Scalar(&bind.CallOpts{}) require.Equal(t, baseFeeScalar, normalScalars.BaseFeeScalar)
require.Nil(t, err, "reading gpo scalar")
if gpoOverhead.Cmp(overheadValue) != 0 { blobBaseFeeScalar, err = gpoContract.BlobBaseFeeScalar(&bind.CallOpts{})
t.Errorf("overhead that was found (%v) is not what was set (%v)", gpoOverhead, overheadValue) require.NoError(t, err, "reading blob base fee scalar")
} require.Equal(t, blobBaseFeeScalar, normalScalars.BlobBaseFeeScalar)
if gpoScalar.Cmp(scalarValue) != 0 {
t.Errorf("scalar that was found (%v) is not what was set (%v)", gpoScalar, scalarValue)
}
} }
// TestL2SequencerRPCDepositTx checks that the L2 sequencer will not accept DepositTx type transactions. // TestL2SequencerRPCDepositTx checks that the L2 sequencer will not accept DepositTx type transactions.
......
...@@ -2,18 +2,21 @@ package test ...@@ -2,18 +2,21 @@ package test
import ( import (
"context" "context"
"math/big"
"testing" "testing"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi" "github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
) )
var gasLimit = eth.Uint64Quantity(30_000_000) var gasLimit = eth.Uint64Quantity(30_000_000)
...@@ -109,7 +112,7 @@ func RunEngineAPITests(t *testing.T, createBackend func(t *testing.T) engineapi. ...@@ -109,7 +112,7 @@ func RunEngineAPITests(t *testing.T, createBackend func(t *testing.T) engineapi.
payload := envelope.ExecutionPayload payload := envelope.ExecutionPayload
api.assert.Equal(genesis.Hash(), payload.ParentHash, "should have old block as parent") api.assert.Equal(genesis.Hash(), payload.ParentHash, "should have old block as parent")
api.newPayload(payload) api.newPayload(envelope)
api.forkChoiceUpdated(payload.BlockHash, genesis.Hash(), genesis.Hash()) api.forkChoiceUpdated(payload.BlockHash, genesis.Hash(), genesis.Hash())
api.assert.Equal(payload.BlockHash, api.headHash(), "should reorg to block built on old parent") api.assert.Equal(payload.BlockHash, api.headHash(), "should reorg to block built on old parent")
}) })
...@@ -138,13 +141,12 @@ func RunEngineAPITests(t *testing.T, createBackend func(t *testing.T) engineapi. ...@@ -138,13 +141,12 @@ func RunEngineAPITests(t *testing.T, createBackend func(t *testing.T) engineapi.
// Build a valid block // Build a valid block
payloadID := api.startBlockBuilding(genesis, eth.Uint64Quantity(genesis.Time+2)) payloadID := api.startBlockBuilding(genesis, eth.Uint64Quantity(genesis.Time+2))
envelope := api.getPayload(payloadID) envelope := api.getPayload(payloadID)
newBlock := envelope.ExecutionPayload
// But then make it invalid by changing the state root // But then make it invalid by changing the state root
newBlock.StateRoot = eth.Bytes32(genesis.TxHash) envelope.ExecutionPayload.StateRoot = eth.Bytes32(genesis.TxHash)
updateBlockHash(envelope) updateBlockHash(envelope)
r, err := api.engine.NewPayloadV2(api.ctx, newBlock) r, err := api.callNewPayload(envelope)
api.assert.NoError(err) api.assert.NoError(err)
api.assert.Equal(eth.ExecutionInvalid, r.Status) api.assert.Equal(eth.ExecutionInvalid, r.Status)
}) })
...@@ -156,13 +158,12 @@ func RunEngineAPITests(t *testing.T, createBackend func(t *testing.T) engineapi. ...@@ -156,13 +158,12 @@ func RunEngineAPITests(t *testing.T, createBackend func(t *testing.T) engineapi.
// Start with a valid time // Start with a valid time
payloadID := api.startBlockBuilding(genesis, eth.Uint64Quantity(genesis.Time+1)) payloadID := api.startBlockBuilding(genesis, eth.Uint64Quantity(genesis.Time+1))
envelope := api.getPayload(payloadID) envelope := api.getPayload(payloadID)
newBlock := envelope.ExecutionPayload
// Then make it invalid to check NewPayload rejects it // Then make it invalid to check NewPayload rejects it
newBlock.Timestamp = eth.Uint64Quantity(genesis.Time) envelope.ExecutionPayload.Timestamp = eth.Uint64Quantity(genesis.Time)
updateBlockHash(envelope) updateBlockHash(envelope)
r, err := api.engine.NewPayloadV2(api.ctx, newBlock) r, err := api.callNewPayload(envelope)
api.assert.NoError(err) api.assert.NoError(err)
api.assert.Equal(eth.ExecutionInvalid, r.Status) api.assert.Equal(eth.ExecutionInvalid, r.Status)
}) })
...@@ -174,13 +175,12 @@ func RunEngineAPITests(t *testing.T, createBackend func(t *testing.T) engineapi. ...@@ -174,13 +175,12 @@ func RunEngineAPITests(t *testing.T, createBackend func(t *testing.T) engineapi.
// Start with a valid time // Start with a valid time
payloadID := api.startBlockBuilding(genesis, eth.Uint64Quantity(genesis.Time+1)) payloadID := api.startBlockBuilding(genesis, eth.Uint64Quantity(genesis.Time+1))
envelope := api.getPayload(payloadID) envelope := api.getPayload(payloadID)
newBlock := envelope.ExecutionPayload
// Then make it invalid to check NewPayload rejects it // Then make it invalid to check NewPayload rejects it
newBlock.Timestamp = eth.Uint64Quantity(genesis.Time - 1) envelope.ExecutionPayload.Timestamp = eth.Uint64Quantity(genesis.Time - 1)
updateBlockHash(envelope) updateBlockHash(envelope)
r, err := api.engine.NewPayloadV2(api.ctx, newBlock) r, err := api.callNewPayload(envelope)
api.assert.NoError(err) api.assert.NoError(err)
api.assert.Equal(eth.ExecutionInvalid, r.Status) api.assert.Equal(eth.ExecutionInvalid, r.Status)
}) })
...@@ -363,7 +363,7 @@ func (h *testHelper) addBlockWithParent(head *types.Header, timestamp eth.Uint64 ...@@ -363,7 +363,7 @@ func (h *testHelper) addBlockWithParent(head *types.Header, timestamp eth.Uint64
h.assert.Equal(head.Hash(), block.ParentHash, "should have correct parent") h.assert.Equal(head.Hash(), block.ParentHash, "should have correct parent")
h.assert.Len(block.Transactions, len(txs)) h.assert.Len(block.Transactions, len(txs))
h.newPayload(block) h.newPayload(envelope)
// Should not have changed the chain head yet // Should not have changed the chain head yet
h.assert.Equal(prevHead, h.backend.CurrentHeader()) h.assert.Equal(prevHead, h.backend.CurrentHeader())
...@@ -395,25 +395,35 @@ func (h *testHelper) startBlockBuilding(head *types.Header, newBlockTimestamp et ...@@ -395,25 +395,35 @@ func (h *testHelper) startBlockBuilding(head *types.Header, newBlockTimestamp et
txData = append(txData, rlp) txData = append(txData, rlp)
} }
canyonTime := h.backend.Config().CanyonTime attr := &eth.PayloadAttributes{
var w *types.Withdrawals
if canyonTime != nil && *canyonTime <= uint64(newBlockTimestamp) {
w = &types.Withdrawals{}
}
result, err := h.engine.ForkchoiceUpdatedV2(h.ctx, &eth.ForkchoiceState{
HeadBlockHash: head.Hash(),
SafeBlockHash: head.Hash(),
FinalizedBlockHash: head.Hash(),
}, &eth.PayloadAttributes{
Timestamp: newBlockTimestamp, Timestamp: newBlockTimestamp,
PrevRandao: eth.Bytes32(head.MixDigest), PrevRandao: eth.Bytes32(head.MixDigest),
SuggestedFeeRecipient: feeRecipient, SuggestedFeeRecipient: feeRecipient,
Transactions: txData, Transactions: txData,
NoTxPool: true, NoTxPool: true,
GasLimit: &gasLimit, GasLimit: &gasLimit,
Withdrawals: w, }
}) n := new(big.Int).Add(head.Number, big.NewInt(1))
if h.backend.Config().IsShanghai(n, uint64(newBlockTimestamp)) {
attr.Withdrawals = &types.Withdrawals{}
}
if h.backend.Config().IsCancun(n, uint64(newBlockTimestamp)) {
attr.ParentBeaconBlockRoot = &common.Hash{}
}
fcState := &eth.ForkchoiceState{
HeadBlockHash: head.Hash(),
SafeBlockHash: head.Hash(),
FinalizedBlockHash: head.Hash(),
}
var result *eth.ForkchoiceUpdatedResult
var err error
if h.backend.Config().IsCancun(n, uint64(newBlockTimestamp)) {
result, err = h.engine.ForkchoiceUpdatedV3(h.ctx, fcState, attr)
} else if h.backend.Config().IsShanghai(n, uint64(newBlockTimestamp)) {
result, err = h.engine.ForkchoiceUpdatedV2(h.ctx, fcState, attr)
} else {
result, err = h.engine.ForkchoiceUpdatedV1(h.ctx, fcState, attr)
}
h.assert.NoError(err) h.assert.NoError(err)
h.assert.Equal(eth.ExecutionValid, result.PayloadStatus.Status) h.assert.Equal(eth.ExecutionValid, result.PayloadStatus.Status)
id := result.PayloadID id := result.PayloadID
...@@ -423,16 +433,25 @@ func (h *testHelper) startBlockBuilding(head *types.Header, newBlockTimestamp et ...@@ -423,16 +433,25 @@ func (h *testHelper) startBlockBuilding(head *types.Header, newBlockTimestamp et
func (h *testHelper) getPayload(id *eth.PayloadID) *eth.ExecutionPayloadEnvelope { func (h *testHelper) getPayload(id *eth.PayloadID) *eth.ExecutionPayloadEnvelope {
h.Log("getPayload", "id", id) h.Log("getPayload", "id", id)
envelope, err := h.engine.GetPayloadV2(h.ctx, *id) envelope, err := h.engine.GetPayloadV2(h.ctx, *id) // calls the same underlying function as V1 and V3
h.assert.NoError(err) h.assert.NoError(err)
h.assert.NotNil(envelope) h.assert.NotNil(envelope)
h.assert.NotNil(envelope.ExecutionPayload) h.assert.NotNil(envelope.ExecutionPayload)
return envelope return envelope
} }
func (h *testHelper) newPayload(block *eth.ExecutionPayload) { func (h *testHelper) callNewPayload(envelope *eth.ExecutionPayloadEnvelope) (*eth.PayloadStatusV1, error) {
h.Log("newPayload", "hash", block.BlockHash) n := new(big.Int).SetUint64(uint64(envelope.ExecutionPayload.BlockNumber))
r, err := h.engine.NewPayloadV2(h.ctx, block) if h.backend.Config().IsCancun(n, uint64(envelope.ExecutionPayload.Timestamp)) {
return h.engine.NewPayloadV3(h.ctx, envelope.ExecutionPayload, []common.Hash{}, envelope.ParentBeaconBlockRoot)
} else {
return h.engine.NewPayloadV2(h.ctx, envelope.ExecutionPayload)
}
}
func (h *testHelper) newPayload(envelope *eth.ExecutionPayloadEnvelope) {
h.Log("newPayload", "hash", envelope.ExecutionPayload.BlockHash)
r, err := h.callNewPayload(envelope)
h.assert.NoError(err) h.assert.NoError(err)
h.assert.Equal(eth.ExecutionValid, r.Status) h.assert.Equal(eth.ExecutionValid, r.Status)
h.assert.Nil(r.ValidationError) h.assert.Nil(r.ValidationError)
......
...@@ -48,8 +48,7 @@ CAPELLA_FORK_VERSION: 0x03000001 ...@@ -48,8 +48,7 @@ CAPELLA_FORK_VERSION: 0x03000001
CAPELLA_FORK_EPOCH: 0 CAPELLA_FORK_EPOCH: 0
# DENEB # DENEB
DENEB_FORK_VERSION: 0x04000001 DENEB_FORK_VERSION: 0x04000001
# TODO: activate Deneb at genesis DENEB_FORK_EPOCH: 0
DENEB_FORK_EPOCH: 1
# EIP6110 # EIP6110
EIP6110_FORK_VERSION: 0x05000001 EIP6110_FORK_VERSION: 0x05000001
......
...@@ -4,7 +4,7 @@ set -eu ...@@ -4,7 +4,7 @@ set -eu
echo "eth2-testnet-genesis path: $(which eth2-testnet-genesis)" echo "eth2-testnet-genesis path: $(which eth2-testnet-genesis)"
eth2-testnet-genesis capella \ eth2-testnet-genesis deneb \
--config=./beacon-data/config.yaml \ --config=./beacon-data/config.yaml \
--preset-phase0=minimal \ --preset-phase0=minimal \
--preset-altair=minimal \ --preset-altair=minimal \
......
...@@ -46,8 +46,9 @@ ...@@ -46,8 +46,9 @@
"l2GenesisRegolithTimeOffset": "0x0", "l2GenesisRegolithTimeOffset": "0x0",
"l2GenesisCanyonTimeOffset": "0x0", "l2GenesisCanyonTimeOffset": "0x0",
"l2GenesisDeltaTimeOffset": "0x0", "l2GenesisDeltaTimeOffset": "0x0",
"l2GenesisEcotoneTimeOffset": "0x40", "l2GenesisEcotoneTimeOffset": "0x0",
"l1CancunTimeOffset": "0x30", "l2GenesisFjordTimeOffset": "0x0",
"l1CancunTimeOffset": "0x0",
"systemConfigStartBlock": 0, "systemConfigStartBlock": 0,
"requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", "requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000",
"recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment