diff --git a/op-chain-ops/genesis/config.go b/op-chain-ops/genesis/config.go index 034564ead629e..72f4eaef542bb 100644 --- a/op-chain-ops/genesis/config.go +++ b/op-chain-ops/genesis/config.go @@ -418,10 +418,10 @@ func (d *UpgradeScheduleDeployConfig) ForkTimeOffset(fork rollup.ForkName) *uint return (*uint64)(d.L2GenesisHoloceneTimeOffset) case rollup.Isthmus: return (*uint64)(d.L2GenesisIsthmusTimeOffset) - case rollup.Interop: - return (*uint64)(d.L2GenesisInteropTimeOffset) case rollup.Jovian: return (*uint64)(d.L2GenesisJovianTimeOffset) + case rollup.Interop: + return (*uint64)(d.L2GenesisInteropTimeOffset) default: panic(fmt.Sprintf("unknown fork: %s", fork)) } @@ -445,10 +445,10 @@ func (d *UpgradeScheduleDeployConfig) SetForkTimeOffset(fork rollup.ForkName, of d.L2GenesisHoloceneTimeOffset = (*hexutil.Uint64)(offset) case rollup.Isthmus: d.L2GenesisIsthmusTimeOffset = (*hexutil.Uint64)(offset) - case rollup.Interop: - d.L2GenesisInteropTimeOffset = (*hexutil.Uint64)(offset) case rollup.Jovian: d.L2GenesisJovianTimeOffset = (*hexutil.Uint64)(offset) + case rollup.Interop: + d.L2GenesisInteropTimeOffset = (*hexutil.Uint64)(offset) default: panic(fmt.Sprintf("unknown fork: %s", fork)) } @@ -560,7 +560,6 @@ func (d *UpgradeScheduleDeployConfig) forks() []Fork { {L2GenesisTimeOffset: d.L2GenesisGraniteTimeOffset, Name: string(L2AllocsGranite)}, {L2GenesisTimeOffset: d.L2GenesisHoloceneTimeOffset, Name: string(L2AllocsHolocene)}, {L2GenesisTimeOffset: d.L2GenesisIsthmusTimeOffset, Name: string(L2AllocsIsthmus)}, - {L2GenesisTimeOffset: d.L2GenesisInteropTimeOffset, Name: string(L2AllocsInterop)}, {L2GenesisTimeOffset: d.L2GenesisJovianTimeOffset, Name: string(L2AllocsJovian)}, } } diff --git a/op-chain-ops/genesis/config_test.go b/op-chain-ops/genesis/config_test.go index ad2308cc89c11..ddb69320c071f 100644 --- a/op-chain-ops/genesis/config_test.go +++ b/op-chain-ops/genesis/config_test.go @@ -211,8 +211,7 @@ func TestUpgradeScheduleDeployConfig_SolidityForkNumber(t *testing.T) { {rollup.Granite, 4}, {rollup.Holocene, 5}, {rollup.Isthmus, 6}, - {rollup.Interop, 7}, - {rollup.Jovian, 8}, + {rollup.Jovian, 7}, } for _, tt := range tests { var d UpgradeScheduleDeployConfig diff --git a/op-chain-ops/genesis/layer_two.go b/op-chain-ops/genesis/layer_two.go index 9f0103e2815ed..0729eb770d409 100644 --- a/op-chain-ops/genesis/layer_two.go +++ b/op-chain-ops/genesis/layer_two.go @@ -29,7 +29,6 @@ const ( L2AllocsGranite L2AllocsMode = "granite" L2AllocsHolocene L2AllocsMode = "holocene" L2AllocsIsthmus L2AllocsMode = "isthmus" - L2AllocsInterop L2AllocsMode = "interop" L2AllocsJovian L2AllocsMode = "jovian" ) diff --git a/op-chain-ops/interopgen/deploy.go b/op-chain-ops/interopgen/deploy.go index 75a45a1c87c97..ec6356f8632e0 100644 --- a/op-chain-ops/interopgen/deploy.go +++ b/op-chain-ops/interopgen/deploy.go @@ -101,7 +101,7 @@ func Deploy(logger log.Logger, fa *foundry.ArtifactsFS, srcFS *foundry.SourceMap if err := l2Host.EnableCheats(); err != nil { return nil, nil, fmt.Errorf("failed to enable cheats in L2 state %s: %w", l2ChainID, err) } - if err := GenesisL2(l2Host, l2Cfg, deployments.L2s[l2ChainID], len(cfg.L2s) > 1); err != nil { + if err := GenesisL2(l2Host, l2Cfg, deployments.L2s[l2ChainID]); err != nil { return nil, nil, fmt.Errorf("failed to apply genesis data to L2 %s: %w", l2ChainID, err) } l2Out, err := CompleteL2(l2Host, l2Cfg, l1GenesisBlock, deployments.L2s[l2ChainID]) @@ -283,7 +283,7 @@ func MigrateInterop( }, nil } -func GenesisL2(l2Host *script.Host, cfg *L2Config, deployment *L2Deployment, multichainDepSet bool) error { +func GenesisL2(l2Host *script.Host, cfg *L2Config, deployment *L2Deployment) error { genesisScript, err := opcm.NewL2GenesisScript(l2Host) if err != nil { return fmt.Errorf("failed to create L2 genesis script: %w", err) @@ -307,9 +307,10 @@ func GenesisL2(l2Host *script.Host, cfg *L2Config, deployment *L2Deployment, mul L1FeeVaultWithdrawalNetwork: big.NewInt(int64(cfg.L1FeeVaultWithdrawalNetwork.ToUint8())), GovernanceTokenOwner: cfg.GovernanceTokenOwner, Fork: big.NewInt(cfg.SolidityForkNumber(1)), - DeployCrossL2Inbox: multichainDepSet, - EnableGovernance: cfg.EnableGovernance, - FundDevAccounts: cfg.FundDevAccounts, + // Only include interop predeploys if it is activating at genesis + UseInterop: cfg.L2GenesisInteropTimeOffset != nil && *cfg.L2GenesisInteropTimeOffset == 0, + EnableGovernance: cfg.EnableGovernance, + FundDevAccounts: cfg.FundDevAccounts, }); err != nil { return fmt.Errorf("failed L2 genesis: %w", err) } diff --git a/op-deployer/pkg/deployer/bootstrap/flags.go b/op-deployer/pkg/deployer/bootstrap/flags.go index a1681f3bd4188..9eea043aa2801 100644 --- a/op-deployer/pkg/deployer/bootstrap/flags.go +++ b/op-deployer/pkg/deployer/bootstrap/flags.go @@ -85,7 +85,6 @@ var ( Name: L1ContractsReleaseFlagName, Usage: "L1 contracts release", EnvVars: deployer.PrefixEnvVar("L1_CONTRACTS_RELEASE"), - Value: "dev", } ProtocolVersionsOwnerFlag = &cli.StringFlag{ Name: ProtocolVersionsOwnerFlagName, diff --git a/op-deployer/pkg/deployer/integration_test/apply_test.go b/op-deployer/pkg/deployer/integration_test/apply_test.go index c7bcdf570dd36..61aa4b002b5fa 100644 --- a/op-deployer/pkg/deployer/integration_test/apply_test.go +++ b/op-deployer/pkg/deployer/integration_test/apply_test.go @@ -3,13 +3,17 @@ package integration_test import ( "bytes" "context" + "crypto/ecdsa" "encoding/hex" - "fmt" "log/slog" "math/big" - "os" + "regexp" "strings" "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/bootstrap" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum-optimism/optimism/op-service/testutils" "github.com/ethereum-optimism/optimism/op-service/testutils/devnet" @@ -42,8 +46,6 @@ import ( "github.com/stretchr/testify/require" ) -const defaultL1ChainID uint64 = 77799777 - type deployerKey struct{} func (d *deployerKey) HDPath() string { @@ -54,106 +56,125 @@ func (d *deployerKey) String() string { return "deployer-key" } -func TestLiveChain(t *testing.T) { - t.Skip("requires backport") +func defaultPrivkey(t *testing.T) (string, *ecdsa.PrivateKey, *devkeys.MnemonicDevKeys) { + pkHex := "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + pk, err := crypto.HexToECDSA(pkHex) + require.NoError(t, err) - op_e2e.InitParallel(t) + dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic) + require.NoError(t, err) - for _, network := range []string{"mainnet", "sepolia"} { - t.Run(network, func(t *testing.T) { - testLiveChainNetwork(t, network) - }) - } + return pkHex, pk, dk } -func testLiveChainNetwork(t *testing.T, network string) { +// TestEndToEndBootstrapApply tests that a system can be fully bootstrapped and applied, both from +// local artifacts and the default tagged artifacts. The tagged artifacts test only runs on proposal +// or backports branches, since those are the only branches with an SLA to support tagged artifacts. +func TestEndToEndBootstrapApply(t *testing.T) { op_e2e.InitParallel(t) - lgr := testlog.Logger(t, slog.LevelInfo) - rpcURL := os.Getenv(fmt.Sprintf("%s_RPC_URL", strings.ToUpper(network))) - require.NotEmpty(t, rpcURL) - forkedL1, cleanup, err := devnet.NewForked(lgr, rpcURL) - require.NoError(t, err) - t.Cleanup(func() { - require.NoError(t, cleanup()) - }) + lgr := testlog.Logger(t, slog.LevelDebug) + l1RPC, l1Client := devnet.DefaultAnvilRPC(t, lgr) + pkHex, pk, dk := defaultPrivkey(t) + l1ChainID := new(big.Int).SetUint64(devnet.DefaultChainID) + l2ChainID := uint256.NewInt(1) + testCacheDir := testutils.IsolatedTestDirWithAutoCleanup(t) + superchainPAO := common.Address{'S', 'P', 'A', 'O'} + + apply := func(t *testing.T, loc *artifacts.Locator) { + ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second) + defer cancel() + + bstrap, err := bootstrap.Superchain(ctx, bootstrap.SuperchainConfig{ + L1RPCUrl: l1RPC, + PrivateKey: pkHex, + Logger: lgr, + ArtifactsLocator: loc, + CacheDir: testCacheDir, + SuperchainProxyAdminOwner: superchainPAO, + ProtocolVersionsOwner: common.Address{'P', 'V', 'O'}, + Guardian: common.Address{'G'}, + Paused: false, + RecommendedProtocolVersion: params.ProtocolVersion{0x01, 0x02, 0x03, 0x04}, + RequiredProtocolVersion: params.ProtocolVersion{0x01, 0x02, 0x03, 0x04}, + }) + require.NoError(t, err) - l1Client, err := ethclient.Dial(forkedL1.RPCUrl()) - require.NoError(t, err) + var release string + if !loc.IsTag() { + release = "dev" + } - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + impls, err := bootstrap.Implementations(ctx, bootstrap.ImplementationsConfig{ + L1RPCUrl: l1RPC, + PrivateKey: pkHex, + ArtifactsLocator: loc, + L1ContractsRelease: release, + MIPSVersion: int(standard.MIPSVersion), + WithdrawalDelaySeconds: standard.WithdrawalDelaySeconds, + MinProposalSizeBytes: standard.MinProposalSizeBytes, + ChallengePeriodSeconds: standard.ChallengePeriodSeconds, + ProofMaturityDelaySeconds: standard.ProofMaturityDelaySeconds, + DisputeGameFinalityDelaySeconds: standard.DisputeGameFinalityDelaySeconds, + SuperchainConfigProxy: bstrap.SuperchainConfigProxy, + ProtocolVersionsProxy: bstrap.ProtocolVersionsProxy, + UpgradeController: superchainPAO, + SuperchainProxyAdmin: bstrap.SuperchainProxyAdmin, + CacheDir: testCacheDir, + Logger: lgr, + }) + require.NoError(t, err) - l1ChainID, err := l1Client.ChainID(ctx) - require.NoError(t, err) + intent, st := newIntent(t, l1ChainID, dk, l2ChainID, loc, loc) + intent.SuperchainRoles = nil + intent.OPCMAddress = &impls.Opcm - pk, err := crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80") - require.NoError(t, err) - dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic) - require.NoError(t, err) + require.NoError(t, deployer.ApplyPipeline( + ctx, + deployer.ApplyPipelineOpts{ + DeploymentTarget: deployer.DeploymentTargetLive, + L1RPCUrl: l1RPC, + DeployerPrivateKey: pk, + Intent: intent, + State: st, + Logger: lgr, + StateWriter: pipeline.NoopStateWriter(), + CacheDir: testCacheDir, + }, + )) - testCacheDir := testutils.IsolatedTestDirWithAutoCleanup(t) + cg := ethClientCodeGetter(ctx, l1Client) + validateOPChainDeployment(t, cg, st, intent, false) + } - intent, st := newIntent( - t, - l1ChainID, - dk, - uint256.NewInt(9999), - artifacts.DefaultL1ContractsLocator, - artifacts.DefaultL2ContractsLocator, - ) - cg := ethClientCodeGetter(ctx, l1Client) - - require.NoError(t, deployer.ApplyPipeline( - ctx, - deployer.ApplyPipelineOpts{ - DeploymentTarget: deployer.DeploymentTargetLive, - L1RPCUrl: forkedL1.RPCUrl(), - DeployerPrivateKey: pk, - Intent: intent, - State: st, - Logger: lgr, - StateWriter: pipeline.NoopStateWriter(), - CacheDir: testCacheDir, - }, - )) + t.Run("default tagged artifacts", func(t *testing.T) { + op_e2e.InitParallel(t) + testutils.RunOnBranch(t, regexp.MustCompile(`^(backports/op-deployer|proposal/op-contracts)/*`)) + apply(t, artifacts.DefaultL1ContractsLocator) + }) - validateSuperchainDeployment(t, st, cg, false) - validateOPChainDeployment(t, cg, st, intent, false) + t.Run("local artifacts", func(t *testing.T) { + op_e2e.InitParallel(t) + loc, _ := testutil.LocalArtifacts(t) + apply(t, loc) + }) } func TestEndToEndApply(t *testing.T) { op_e2e.InitParallel(t) lgr := testlog.Logger(t, slog.LevelDebug) - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - anvil, err := devnet.NewAnvil(lgr, devnet.WithChainID(77799777)) - require.NoError(t, err) - require.NoError(t, anvil.Start()) - t.Cleanup(func() { - require.NoError(t, anvil.Stop()) - }) - l1RPC := anvil.RPCUrl() - l1Client, err := ethclient.Dial(l1RPC) - require.NoError(t, err) - - pk, err := crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80") - require.NoError(t, err) - - l1ChainID := new(big.Int).SetUint64(defaultL1ChainID) - dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic) - require.NoError(t, err) - + l1RPC, l1Client := devnet.DefaultAnvilRPC(t, lgr) + _, pk, dk := defaultPrivkey(t) + l1ChainID := new(big.Int).SetUint64(devnet.DefaultChainID) l2ChainID1 := uint256.NewInt(1) l2ChainID2 := uint256.NewInt(2) - loc, _ := testutil.LocalArtifacts(t) - testCacheDir := testutils.IsolatedTestDirWithAutoCleanup(t) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + t.Run("two chains one after another", func(t *testing.T) { intent, st := newIntent(t, l1ChainID, dk, l2ChainID1, loc, loc) cg := ethClientCodeGetter(ctx, l1Client) @@ -194,31 +215,6 @@ func TestEndToEndApply(t *testing.T) { validateOPChainDeployment(t, cg, st, intent, false) }) - t.Run("chain with tagged artifacts", func(t *testing.T) { - t.Skip("requires backport") - intent, st := newIntent(t, l1ChainID, dk, l2ChainID1, loc, loc) - intent.L1ContractsLocator = artifacts.DefaultL1ContractsLocator - intent.L2ContractsLocator = artifacts.DefaultL2ContractsLocator - cg := ethClientCodeGetter(ctx, l1Client) - - require.NoError(t, deployer.ApplyPipeline( - ctx, - deployer.ApplyPipelineOpts{ - DeploymentTarget: deployer.DeploymentTargetLive, - L1RPCUrl: l1RPC, - DeployerPrivateKey: pk, - Intent: intent, - State: st, - Logger: lgr, - StateWriter: pipeline.NoopStateWriter(), - CacheDir: testCacheDir, - }, - )) - - validateSuperchainDeployment(t, st, cg, true) - validateOPChainDeployment(t, cg, st, intent, false) - }) - t.Run("with calldata broadcasts and prestate generation", func(t *testing.T) { intent, st := newIntent(t, l1ChainID, dk, l2ChainID1, loc, loc) mockPreStateBuilder := devnet.NewMockPreStateBuilder() @@ -255,7 +251,7 @@ func TestGlobalOverrides(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - opts, intent, st := setupGenesisChain(t, defaultL1ChainID) + opts, intent, st := setupGenesisChain(t, devnet.DefaultChainID) expectedGasLimit := strings.ToLower("0x1C9C380") expectedBaseFeeVaultRecipient := common.HexToAddress("0x0000000000000000000000000000000000000001") expectedL1FeeVaultRecipient := common.HexToAddress("0x0000000000000000000000000000000000000002") @@ -314,7 +310,7 @@ func TestApplyGenesisStrategy(t *testing.T) { } deployChain := func(l1DevGenesisParams *state.L1DevGenesisParams) *state.State { - opts, intent, st := setupGenesisChain(t, defaultL1ChainID) + opts, intent, st := setupGenesisChain(t, devnet.DefaultChainID) intent.L1DevGenesisParams = l1DevGenesisParams require.NoError(t, deployer.ApplyPipeline(ctx, opts)) cg := stateDumpCodeGetter(st) @@ -349,7 +345,7 @@ func TestProofParamOverrides(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - opts, intent, st := setupGenesisChain(t, defaultL1ChainID) + opts, intent, st := setupGenesisChain(t, devnet.DefaultChainID) intent.GlobalDeployOverrides = map[string]any{ "faultGameWithdrawalDelay": standard.WithdrawalDelaySeconds + 1, "preimageOracleMinProposalSize": standard.MinProposalSizeBytes + 1, @@ -446,7 +442,7 @@ func TestAltDADeployment(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - opts, intent, st := setupGenesisChain(t, defaultL1ChainID) + opts, intent, st := setupGenesisChain(t, devnet.DefaultChainID) altDACfg := genesis.AltDADeployConfig{ UseAltDA: true, DACommitmentType: altda.KeccakCommitmentString, @@ -524,7 +520,7 @@ func TestInvalidL2Genesis(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - opts, intent, _ := setupGenesisChain(t, defaultL1ChainID) + opts, intent, _ := setupGenesisChain(t, devnet.DefaultChainID) intent.GlobalDeployOverrides = tt.overrides mockPreStateBuilder := devnet.NewMockPreStateBuilder() @@ -544,7 +540,7 @@ func TestAdditionalDisputeGames(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - opts, intent, st := setupGenesisChain(t, defaultL1ChainID) + opts, intent, st := setupGenesisChain(t, devnet.DefaultChainID) deployerAddr := crypto.PubkeyToAddress(opts.DeployerPrivateKey.PublicKey) (&intent.Chains[0].Roles).L1ProxyAdminOwner = deployerAddr intent.SuperchainRoles.SuperchainGuardian = deployerAddr @@ -628,7 +624,7 @@ func TestIntentConfiguration(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - opts, intent, st := setupGenesisChain(t, defaultL1ChainID) + opts, intent, st := setupGenesisChain(t, devnet.DefaultChainID) tt.mutator(intent) require.NoError(t, deployer.ApplyPipeline(ctx, opts)) tt.assertions(t, st) diff --git a/op-deployer/pkg/deployer/opcm/l2genesis.go b/op-deployer/pkg/deployer/opcm/l2genesis.go index 3f91196cc85fc..1cc075ba816f8 100644 --- a/op-deployer/pkg/deployer/opcm/l2genesis.go +++ b/op-deployer/pkg/deployer/opcm/l2genesis.go @@ -25,7 +25,7 @@ type L2GenesisInput struct { L1FeeVaultWithdrawalNetwork *big.Int GovernanceTokenOwner common.Address Fork *big.Int - DeployCrossL2Inbox bool + UseInterop bool EnableGovernance bool FundDevAccounts bool } diff --git a/op-deployer/pkg/deployer/pipeline/l2genesis.go b/op-deployer/pkg/deployer/pipeline/l2genesis.go index 3ebed12ee8ae5..54c68af053025 100644 --- a/op-deployer/pkg/deployer/pipeline/l2genesis.go +++ b/op-deployer/pkg/deployer/pipeline/l2genesis.go @@ -91,9 +91,10 @@ func GenerateL2Genesis(pEnv *Env, intent *state.Intent, bundle ArtifactsBundle, SequencerFeeVaultRecipient: thisIntent.SequencerFeeVaultRecipient, GovernanceTokenOwner: overrides.GovernanceTokenOwner, Fork: big.NewInt(schedule.SolidityForkNumber(1)), - DeployCrossL2Inbox: len(intent.Chains) > 1, - EnableGovernance: overrides.EnableGovernance, - FundDevAccounts: overrides.FundDevAccounts, + // Only include interop predeploys if it is activating at genesis + UseInterop: schedule.L2GenesisInteropTimeOffset != nil && *schedule.L2GenesisInteropTimeOffset == 0, + EnableGovernance: overrides.EnableGovernance, + FundDevAccounts: overrides.FundDevAccounts, }); err != nil { return fmt.Errorf("failed to call L2Genesis script: %w", err) } diff --git a/op-e2e/actions/helpers/user_test.go b/op-e2e/actions/helpers/user_test.go index cc312c087482e..9cc041a7ab344 100644 --- a/op-e2e/actions/helpers/user_test.go +++ b/op-e2e/actions/helpers/user_test.go @@ -29,8 +29,6 @@ type hardforkScheduledTest struct { graniteTime *hexutil.Uint64 holoceneTime *hexutil.Uint64 isthmusTime *hexutil.Uint64 - interopTime *hexutil.Uint64 - jovianTime *hexutil.Uint64 runToFork string allocType config.AllocType } @@ -45,10 +43,6 @@ func (tc *hardforkScheduledTest) GetFork(fork string) *uint64 { func (tc *hardforkScheduledTest) fork(fork string) **hexutil.Uint64 { switch fork { - case "jovian": - return &tc.jovianTime - case "interop": - return &tc.interopTime case "isthmus": return &tc.isthmusTime case "holocene": @@ -95,8 +89,6 @@ func testCrossLayerUser(t *testing.T, allocType config.AllocType) { "granite", "holocene", "isthmus", - "interop", - "jovian", } for i, fork := range forks { i := i diff --git a/op-e2e/config/init.go b/op-e2e/config/init.go index 254309a89cf57..1edd487db48dd 100644 --- a/op-e2e/config/init.go +++ b/op-e2e/config/init.go @@ -247,7 +247,6 @@ func initAllocType(root string, allocType AllocType) { lgr := log.New() allocModes := []genesis.L2AllocsMode{ - genesis.L2AllocsInterop, genesis.L2AllocsIsthmus, genesis.L2AllocsHolocene, genesis.L2AllocsGranite, diff --git a/op-e2e/e2eutils/setup.go b/op-e2e/e2eutils/setup.go index bfd1d123b4841..b8ba1b774c44e 100644 --- a/op-e2e/e2eutils/setup.go +++ b/op-e2e/e2eutils/setup.go @@ -109,12 +109,6 @@ func Ether(v uint64) *big.Int { } func GetL2AllocsMode(dc *genesis.DeployConfig, t uint64) genesis.L2AllocsMode { - if fork := dc.JovianTime(t); fork != nil && *fork <= 0 { - return genesis.L2AllocsJovian - } - if fork := dc.InteropTime(t); fork != nil && *fork <= 0 { - return genesis.L2AllocsInterop - } if fork := dc.IsthmusTime(t); fork != nil && *fork <= 0 { return genesis.L2AllocsIsthmus } diff --git a/op-node/rollup/chain_spec.go b/op-node/rollup/chain_spec.go index edb046988c563..80dcf14127aa7 100644 --- a/op-node/rollup/chain_spec.go +++ b/op-node/rollup/chain_spec.go @@ -58,8 +58,8 @@ var AllForks = []ForkName{ Granite, Holocene, Isthmus, - Interop, Jovian, + Interop, // ADD NEW FORKS HERE! } @@ -166,6 +166,10 @@ func (s *ChainSpec) MaxSequencerDrift(t uint64) uint64 { } func (s *ChainSpec) CheckForkActivation(log log.Logger, block eth.L2BlockRef) { + if s.currentFork == Interop { + return + } + if s.currentFork == "" { // Initialize currentFork if it is not set yet s.currentFork = Bedrock @@ -193,12 +197,12 @@ func (s *ChainSpec) CheckForkActivation(log log.Logger, block eth.L2BlockRef) { if s.config.IsIsthmus(block.Time) { s.currentFork = Isthmus } - if s.config.IsInterop(block.Time) { - s.currentFork = Interop - } if s.config.IsJovian(block.Time) { s.currentFork = Jovian } + if s.config.IsInterop(block.Time) { + s.currentFork = Interop + } log.Info("Current hardfork version detected", "forkName", s.currentFork) return } @@ -222,10 +226,10 @@ func (s *ChainSpec) CheckForkActivation(log log.Logger, block eth.L2BlockRef) { foundActivationBlock = s.config.IsHoloceneActivationBlock(block.Time) case Isthmus: foundActivationBlock = s.config.IsIsthmusActivationBlock(block.Time) - case Interop: - foundActivationBlock = s.config.IsInteropActivationBlock(block.Time) case Jovian: foundActivationBlock = s.config.IsJovianActivationBlock(block.Time) + case Interop: + foundActivationBlock = s.config.IsInteropActivationBlock(block.Time) } if foundActivationBlock { diff --git a/op-node/rollup/chain_spec_test.go b/op-node/rollup/chain_spec_test.go index f1d2cf53f9705..97c88e6ced4d1 100644 --- a/op-node/rollup/chain_spec_test.go +++ b/op-node/rollup/chain_spec_test.go @@ -47,8 +47,8 @@ var testConfig = Config{ GraniteTime: u64ptr(60), HoloceneTime: u64ptr(70), IsthmusTime: u64ptr(80), - InteropTime: u64ptr(90), - JovianTime: u64ptr(100), + JovianTime: u64ptr(90), + InteropTime: nil, BatchInboxAddress: common.HexToAddress("0xff00000000000000000000000000000000000010"), DepositContractAddress: common.HexToAddress("0xbEb5Fc579115071764c7423A4f12eDde41f106Ed"), L1SystemConfigAddress: common.HexToAddress("0x229047fed2591dbec1eF1118d64F7aF3dB9EB290"), @@ -192,15 +192,9 @@ func TestCheckForkActivation(t *testing.T) { expectedCurrentFork: Isthmus, expectedLog: "Detected hardfork activation block", }, - { - name: "Interop activation", - block: eth.L2BlockRef{Time: 90, Number: 11, Hash: common.Hash{0xb}}, - expectedCurrentFork: Interop, - expectedLog: "Detected hardfork activation block", - }, { name: "Jovian activation", - block: eth.L2BlockRef{Time: 100, Number: 11, Hash: common.Hash{0xb}}, + block: eth.L2BlockRef{Time: 90, Number: 11, Hash: common.Hash{0xb}}, expectedCurrentFork: Jovian, expectedLog: "Detected hardfork activation block", }, diff --git a/op-node/rollup/types.go b/op-node/rollup/types.go index 4bf7f3ad6c49b..907a1269f83ce 100644 --- a/op-node/rollup/types.go +++ b/op-node/rollup/types.go @@ -123,14 +123,14 @@ type Config struct { // Active if IsthmusTime != nil && L2 block timestamp >= *IsthmusTime, inactive otherwise. IsthmusTime *uint64 `json:"isthmus_time,omitempty"` - // InteropTime sets the activation time for an experimental feature-set, activated like a hardfork. - // Active if InteropTime != nil && L2 block timestamp >= *InteropTime, inactive otherwise. - InteropTime *uint64 `json:"interop_time,omitempty"` - // JovianTime sets the activation time of the Jovian network upgrade. // Active if JovianTime != nil && L2 block timestamp >= *JovianTime, inactive otherwise. JovianTime *uint64 `json:"jovian_time,omitempty"` + // InteropTime sets the activation time for an experimental feature-set, activated like a hardfork. + // Active if InteropTime != nil && L2 block timestamp >= *InteropTime, inactive otherwise. + InteropTime *uint64 `json:"interop_time,omitempty"` + // Note: below addresses are part of the block-derivation process, // and required to be the same network-wide to stay in consensus. @@ -611,12 +611,12 @@ func (c *Config) IsActivationBlockForFork(l2BlockTime uint64, forkName ForkName) func (c *Config) ActivateAtGenesis(hardfork ForkName) { // IMPORTANT! ordered from newest to oldest switch hardfork { - case Jovian: - c.JovianTime = new(uint64) - fallthrough case Interop: c.InteropTime = new(uint64) fallthrough + case Jovian: + c.JovianTime = new(uint64) + fallthrough case Isthmus: c.IsthmusTime = new(uint64) fallthrough diff --git a/op-service/testutils/devnet/anvil.go b/op-service/testutils/devnet/anvil.go index 9b8aec9933fbd..841e126722601 100644 --- a/op-service/testutils/devnet/anvil.go +++ b/op-service/testutils/devnet/anvil.go @@ -10,11 +10,17 @@ import ( "strings" "sync" "sync/atomic" + "testing" "time" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/log" ) +const DefaultChainID = 77799777 + type Anvil struct { args map[string]string proc *exec.Cmd @@ -163,3 +169,16 @@ func (r *Anvil) RPCUrl() string { return fmt.Sprintf("http://localhost:%d", port) } + +func DefaultAnvilRPC(t *testing.T, lgr log.Logger) (string, *ethclient.Client) { + anvil, err := NewAnvil(lgr, WithChainID(DefaultChainID)) + require.NoError(t, err) + require.NoError(t, anvil.Start()) + t.Cleanup(func() { + require.NoError(t, anvil.Stop()) + }) + l1RPC := anvil.RPCUrl() + l1Client, err := ethclient.Dial(l1RPC) + require.NoError(t, err) + return l1RPC, l1Client +} diff --git a/op-service/testutils/git.go b/op-service/testutils/git.go new file mode 100644 index 0000000000000..2c5070c2182fa --- /dev/null +++ b/op-service/testutils/git.go @@ -0,0 +1,42 @@ +package testutils + +import ( + "os" + "os/exec" + "regexp" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func currentBranch() (string, error) { + // CircleCI sometimes checks out the branch then changes it to something else (I've seen it show + // up as "ranch" in some cases). This is probably a bug in CircleCI, but we can work around it + // by using the CIRCLE_BRANCH env var if it's available. This is always set to the branch that + // CircleCI is currently checking out. + circleBranch := os.Getenv("CIRCLE_BRANCH") + if circleBranch != "" { + return circleBranch, nil + } + + cmd := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD") + out, err := cmd.Output() + if err != nil { + return "", err + } + return strings.TrimSpace(string(out)), nil +} + +// RunOnBranch skips the current test unless the current Git branch matches the provided regex. +// This method shells out to git. Any failures running git are considered test failures. +func RunOnBranch(t *testing.T, re *regexp.Regexp) { + t.Helper() + + branch, err := currentBranch() + require.NoError(t, err, "could not get current branch") + + if !re.MatchString(branch) { + t.Skipf("branch %s does not match %s, skipping", branch, re.String()) + } +} diff --git a/packages/contracts-bedrock/scripts/L2Genesis.s.sol b/packages/contracts-bedrock/scripts/L2Genesis.s.sol index 6cf80076b19cb..97c1460e61ec3 100644 --- a/packages/contracts-bedrock/scripts/L2Genesis.s.sol +++ b/packages/contracts-bedrock/scripts/L2Genesis.s.sol @@ -59,7 +59,7 @@ contract L2Genesis is Script { uint256 l1FeeVaultWithdrawalNetwork; address governanceTokenOwner; uint256 fork; - bool deployCrossL2Inbox; + bool useInterop; bool enableGovernance; bool fundDevAccounts; bool deploySoulGasToken; @@ -158,10 +158,6 @@ contract L2Genesis is Script { return; } - if (forkEquals(_fork, Fork.INTEROP)) { - return; - } - if (forkEquals(_fork, Fork.JOVIAN)) { return; } @@ -199,7 +195,7 @@ contract L2Genesis is Script { vm.etch(addr, code); EIP1967Helper.setAdmin(addr, Predeploys.PROXY_ADMIN); - if (Predeploys.isSupportedPredeploy(addr, _input.fork, _input.deployCrossL2Inbox)) { + if (Predeploys.isSupportedPredeploy(addr, _input.useInterop)) { address implementation = Predeploys.predeployToCodeNamespace(addr); EIP1967Helper.setImplementation(addr, implementation); } @@ -235,16 +231,12 @@ contract L2Genesis is Script { setEAS(); // 21 if (_input.deploySoulGasToken) setSoulGasToken(_input); // 800 setGovernanceToken(_input); // 42: OP (not behind a proxy) - if (_input.fork >= uint256(Fork.INTEROP)) { - if (_input.deployCrossL2Inbox) { - setCrossL2Inbox(); // 22 - } + if (_input.useInterop) { + setCrossL2Inbox(); // 22 setL2ToL2CrossDomainMessenger(); // 23 } } - function setInteropPredeployProxies() internal { } - function setProxyAdmin(Input memory _input) internal { // Note the ProxyAdmin implementation itself is behind a proxy that owns itself. address impl = _setImplementationCode(Predeploys.PROXY_ADMIN); diff --git a/packages/contracts-bedrock/scripts/libraries/Config.sol b/packages/contracts-bedrock/scripts/libraries/Config.sol index 2e7f032d86b9b..de18623857ede 100644 --- a/packages/contracts-bedrock/scripts/libraries/Config.sol +++ b/packages/contracts-bedrock/scripts/libraries/Config.sol @@ -36,7 +36,6 @@ enum Fork { GRANITE, HOLOCENE, ISTHMUS, - INTEROP, JOVIAN } diff --git a/packages/contracts-bedrock/test/L2/Predeploys.t.sol b/packages/contracts-bedrock/test/L2/Predeploys.t.sol index 988d35f324dd1..ce84799423815 100644 --- a/packages/contracts-bedrock/test/L2/Predeploys.t.sol +++ b/packages/contracts-bedrock/test/L2/Predeploys.t.sol @@ -8,7 +8,6 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; import { ForgeArtifacts } from "scripts/libraries/ForgeArtifacts.sol"; -import { Fork } from "scripts/libraries/Config.sol"; /// @title PredeploysTest contract PredeploysBaseTest is CommonTest { @@ -55,7 +54,7 @@ contract PredeploysBaseTest is CommonTest { ); } - function _test_predeploys(Fork _fork, bool _enableCrossL2Inbox) internal { + function _test_predeploys(bool _useInterop) internal { uint256 count = 2048; uint160 prefix = uint160(0x420) << 148; @@ -70,7 +69,7 @@ contract PredeploysBaseTest is CommonTest { continue; } - bool isPredeploy = Predeploys.isSupportedPredeploy(addr, uint256(_fork), _enableCrossL2Inbox); + bool isPredeploy = Predeploys.isSupportedPredeploy(addr, _useInterop); bytes memory code = addr.code; if (isPredeploy) assertTrue(code.length > 0); @@ -123,7 +122,7 @@ contract PredeploysTest is PredeploysBaseTest { /// @dev Tests that the predeploy addresses are set correctly. They have code /// and the proxied accounts have the correct admin. function test_predeploys_succeeds() external { - _test_predeploys(Fork.ISTHMUS, false); + _test_predeploys(false); } } @@ -136,13 +135,7 @@ contract PredeploysInteropTest is PredeploysBaseTest { /// @dev Tests that the predeploy addresses are set correctly. They have code /// and the proxied accounts have the correct admin. Using interop. - function test_predeploysWithInbox_succeeds() external { - _test_predeploys(Fork.INTEROP, true); - } - - /// @dev Tests that the predeploy addresses are set correctly. They have code - /// and the proxied accounts have the correct admin. Using interop. - function test_predeploysWithoutInbox_succeeds() external { - _test_predeploys(Fork.INTEROP, false); + function test_predeploys_succeeds() external { + _test_predeploys(true); } } diff --git a/packages/contracts-bedrock/test/setup/Setup.sol b/packages/contracts-bedrock/test/setup/Setup.sol index caf9e2823f7a4..add3ab75761f0 100644 --- a/packages/contracts-bedrock/test/setup/Setup.sol +++ b/packages/contracts-bedrock/test/setup/Setup.sol @@ -318,7 +318,7 @@ contract Setup { l1FeeVaultWithdrawalNetwork: deploy.cfg().l1FeeVaultWithdrawalNetwork(), governanceTokenOwner: deploy.cfg().governanceTokenOwner(), fork: uint256(l2Fork), - deployCrossL2Inbox: deploy.cfg().useInterop(), + useInterop: deploy.cfg().useInterop(), enableGovernance: deploy.cfg().enableGovernance(), fundDevAccounts: deploy.cfg().fundDevAccounts(), deploySoulGasToken: deploy.cfg().deploySoulGasToken(),