From 129c098ca3bd16f98c61c908d1db4397467a131b Mon Sep 17 00:00:00 2001 From: inphi Date: Tue, 7 Oct 2025 19:11:11 -0400 Subject: [PATCH 1/2] op-acceptance-tests: Add smoke tests for disputegamev2 --- .../tests/base/disputegame_v2/init_test.go | 11 ++++++++ .../tests/base/disputegame_v2/smoke_test.go | 26 +++++++++++++++++++ op-chain-ops/interopgen/deploy.go | 7 ++--- .../pkg/deployer/bootstrap/implementations.go | 2 +- op-deployer/pkg/deployer/devfeatures.go | 12 ++++----- .../dsl/proofs/dispute_game_factory.go | 8 +++++- op-devstack/dsl/proofs/game_helper.go | 2 +- op-devstack/presets/disputegame_v2.go | 11 ++++++++ op-devstack/presets/minimal.go | 5 ++++ op-devstack/sysgo/system.go | 4 +-- .../txintent/bindings/DisputeGameFactory.go | 1 + 11 files changed, 73 insertions(+), 16 deletions(-) create mode 100644 op-acceptance-tests/tests/base/disputegame_v2/init_test.go create mode 100644 op-acceptance-tests/tests/base/disputegame_v2/smoke_test.go create mode 100644 op-devstack/presets/disputegame_v2.go diff --git a/op-acceptance-tests/tests/base/disputegame_v2/init_test.go b/op-acceptance-tests/tests/base/disputegame_v2/init_test.go new file mode 100644 index 0000000000000..7f14f8776a715 --- /dev/null +++ b/op-acceptance-tests/tests/base/disputegame_v2/init_test.go @@ -0,0 +1,11 @@ +package disputegame_v2 + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-devstack/presets" +) + +func TestMain(m *testing.M) { + presets.DoMain(m, presets.WithMinimal(), presets.WithDisputeGameV2()) +} diff --git a/op-acceptance-tests/tests/base/disputegame_v2/smoke_test.go b/op-acceptance-tests/tests/base/disputegame_v2/smoke_test.go new file mode 100644 index 0000000000000..c6e8d20ccd37e --- /dev/null +++ b/op-acceptance-tests/tests/base/disputegame_v2/smoke_test.go @@ -0,0 +1,26 @@ +package disputegame_v2 + +import ( + "testing" + + challengerTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-devstack/devtest" + "github.com/ethereum-optimism/optimism/op-devstack/presets" +) + +func TestSmoke(gt *testing.T) { + t := devtest.SerialT(gt) + sys := presets.NewMinimal(t) + require := t.Require() + dgf := sys.DisputeGameFactory() + + gameArgs := dgf.GameArgs(challengerTypes.PermissionedGameType) + require.NotEmpty(gameArgs, "game args is must be set for permissioned v2 dispute games") + gameArgs = dgf.GameArgs(challengerTypes.CannonGameType) + require.NotEmpty(gameArgs, "game args is must be set for cannon v2 dispute games") + + permissionedGame := dgf.GameImpl(challengerTypes.PermissionedGameType) + require.NotEmpty(permissionedGame.Address, "permissioned game impl must be set") + cannonGame := dgf.GameImpl(challengerTypes.CannonGameType) + require.NotEmpty(cannonGame.Address, "cannon game impl must be set") +} diff --git a/op-chain-ops/interopgen/deploy.go b/op-chain-ops/interopgen/deploy.go index 8b52b2f40944c..987e6683ae3b4 100644 --- a/op-chain-ops/interopgen/deploy.go +++ b/op-chain-ops/interopgen/deploy.go @@ -18,6 +18,7 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis/beacondeposit" "github.com/ethereum-optimism/optimism/op-chain-ops/script" + "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/manage" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm" "github.com/ethereum-optimism/optimism/op-service/eth" @@ -27,10 +28,6 @@ var ( // sysGenesisDeployer is used as tx.origin/msg.sender on system genesis script calls. // At the end we verify none of the deployed contracts persist (there may be temporary ones, to insert bytecode). sysGenesisDeployer = common.Address(crypto.Keccak256([]byte("System genesis deployer"))[12:]) - - // OptimismPortalInteropDevFlag is the feature bitmap that enables the OptimismPortalInterop contract. - OptimismPortalInteropDevFlag = common.Hash{31: 0x01} // 0x0000000000000000000000000000000000000000000000000000000000000001 - ) func Deploy(logger log.Logger, fa *foundry.ArtifactsFS, srcFS *foundry.SourceMapFS, cfg *WorldConfig) (*WorldDeployment, *WorldOutput, error) { @@ -195,7 +192,7 @@ func DeploySuperchainToL1(l1Host *script.Host, opcmScripts *opcm.Scripts, superC ProofMaturityDelaySeconds: superCfg.Implementations.FaultProof.ProofMaturityDelaySeconds, DisputeGameFinalityDelaySeconds: superCfg.Implementations.FaultProof.DisputeGameFinalityDelaySeconds, MipsVersion: superCfg.Implementations.FaultProof.MipsVersion, - DevFeatureBitmap: OptimismPortalInteropDevFlag, + DevFeatureBitmap: deployer.OptimismPortalInteropDevFlag, FaultGameV2MaxGameDepth: big.NewInt(73), FaultGameV2SplitDepth: big.NewInt(30), FaultGameV2ClockExtension: big.NewInt(10800), diff --git a/op-deployer/pkg/deployer/bootstrap/implementations.go b/op-deployer/pkg/deployer/bootstrap/implementations.go index 13e577407302e..f6e6d17e17254 100644 --- a/op-deployer/pkg/deployer/bootstrap/implementations.go +++ b/op-deployer/pkg/deployer/bootstrap/implementations.go @@ -94,7 +94,7 @@ func (c *ImplementationsConfig) Check() error { return errors.New("dispute game finality delay in seconds must be specified") } // Check V2 fault game parameters only if V2 dispute games feature is enabled - deployV2Games := deployer.IsDevFeatureEnabled(c.DevFeatureBitmap, deployer.DeployV2DisputeGames) + deployV2Games := deployer.IsDevFeatureEnabled(c.DevFeatureBitmap, deployer.DeployV2DisputeGamesDevFlag) if deployV2Games { if c.FaultGameMaxGameDepth == 0 { return errors.New("fault game max game depth must be specified when V2 dispute games feature is enabled") diff --git a/op-deployer/pkg/deployer/devfeatures.go b/op-deployer/pkg/deployer/devfeatures.go index fff5b073fd3ab..8e62bb1a42fd4 100644 --- a/op-deployer/pkg/deployer/devfeatures.go +++ b/op-deployer/pkg/deployer/devfeatures.go @@ -9,14 +9,14 @@ import ( // Development feature flag constants that mirror the solidity DevFeatures library. // These use a 32 byte bitmap for easy integration between op-deployer and contracts. var ( - // OptimismPortalInterop enables the OptimismPortalInterop contract. - OptimismPortalInterop = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001") + // OptimismPortalInteropDevFlag enables the OptimismPortalInterop contract. + OptimismPortalInteropDevFlag = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001") - // CannonKona enables Kona as the default cannon prover. - CannonKona = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000010") + // CannonKonaDevFlag enables Kona as the default cannon prover. + CannonKonaDevFlag = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000010") - // DeployV2DisputeGames enables deployment of V2 dispute game contracts. - DeployV2DisputeGames = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000100") + // DeployV2DisputeGamesDevFlag enables deployment of V2 dispute game contracts. + DeployV2DisputeGamesDevFlag = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000100") ) // IsDevFeatureEnabled checks if a specific development feature is enabled in a feature bitmap. diff --git a/op-devstack/dsl/proofs/dispute_game_factory.go b/op-devstack/dsl/proofs/dispute_game_factory.go index d2c9f904dea54..3dc0166df0440 100644 --- a/op-devstack/dsl/proofs/dispute_game_factory.go +++ b/op-devstack/dsl/proofs/dispute_game_factory.go @@ -112,12 +112,16 @@ func (f *DisputeGameFactory) GameAtIndex(idx int64) *FaultDisputeGame { return NewFaultDisputeGame(f.t, f.require, gameInfo.Proxy, f.getGameHelper, game) } -func (f *DisputeGameFactory) gameImpl(gameType challengerTypes.GameType) *FaultDisputeGame { +func (f *DisputeGameFactory) GameImpl(gameType challengerTypes.GameType) *FaultDisputeGame { implAddr := contract.Read(f.dgf.GameImpls(uint32(gameType))) game := bindings.NewFaultDisputeGame(bindings.WithClient(f.ethClient), bindings.WithTo(implAddr), bindings.WithTest(f.t)) return NewFaultDisputeGame(f.t, f.require, implAddr, f.getGameHelper, game) } +func (f *DisputeGameFactory) GameArgs(gameType challengerTypes.GameType) []byte { + return contract.Read(f.dgf.GameArgs(uint32(gameType))) +} + func (f *DisputeGameFactory) WaitForGame() *FaultDisputeGame { initialCount := f.GameCount() f.t.Require().Eventually(func() bool { @@ -131,6 +135,7 @@ func (f *DisputeGameFactory) WaitForGame() *FaultDisputeGame { } func (f *DisputeGameFactory) StartSuperCannonGame(eoa *dsl.EOA, opts ...GameOpt) *SuperFaultDisputeGame { + f.require.NotNil(f.supervisor, "supervisor is required to start super games") proposalTimestamp := f.supervisor.FetchSyncStatus().SafeTimestamp return f.startSuperCannonGameOfType(eoa, proposalTimestamp, challengerTypes.SuperCannonGameType, opts...) @@ -151,6 +156,7 @@ func (f *DisputeGameFactory) startSuperCannonGameOfType(eoa *dsl.EOA, timestamp } func (f *DisputeGameFactory) createSuperGameExtraData(timestamp uint64, cfg *GameCfg) []byte { + f.require.NotNil(f.supervisor, "supervisor is required create super games") if !cfg.allowFuture { f.supervisor.AwaitMinCrossSafeTimestamp(timestamp) } diff --git a/op-devstack/dsl/proofs/game_helper.go b/op-devstack/dsl/proofs/game_helper.go index af076b7c9a9e4..a507530395870 100644 --- a/op-devstack/dsl/proofs/game_helper.go +++ b/op-devstack/dsl/proofs/game_helper.go @@ -142,7 +142,7 @@ func (gs *GameHelper) CreateGameWithClaims( data, err := gs.abi.Pack("createGameWithClaims", factory.Address(), gameType, rootClaim, extraData, moves) gs.require.NoError(err) - gameImpl := factory.gameImpl(gameType) + gameImpl := factory.GameImpl(gameType) bonds := factory.initBond(gameType) bonds = bonds.Add(gs.totalMoveBonds(gameImpl, moves)) diff --git a/op-devstack/presets/disputegame_v2.go b/op-devstack/presets/disputegame_v2.go new file mode 100644 index 0000000000000..a47a1cf088b9d --- /dev/null +++ b/op-devstack/presets/disputegame_v2.go @@ -0,0 +1,11 @@ +package presets + +import ( + "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer" + "github.com/ethereum-optimism/optimism/op-devstack/stack" + "github.com/ethereum-optimism/optimism/op-devstack/sysgo" +) + +func WithDisputeGameV2() stack.CommonOption { + return stack.MakeCommon(sysgo.WithDeployerOptions(sysgo.WithDevFeatureBitmap(deployer.DeployV2DisputeGamesDevFlag))) +} diff --git a/op-devstack/presets/minimal.go b/op-devstack/presets/minimal.go index 2e0132f01520f..d97d3b1c7ab39 100644 --- a/op-devstack/presets/minimal.go +++ b/op-devstack/presets/minimal.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum-optimism/optimism/op-devstack/devtest" "github.com/ethereum-optimism/optimism/op-devstack/dsl" + "github.com/ethereum-optimism/optimism/op-devstack/dsl/proofs" "github.com/ethereum-optimism/optimism/op-devstack/shim" "github.com/ethereum-optimism/optimism/op-devstack/stack" "github.com/ethereum-optimism/optimism/op-devstack/stack/match" @@ -42,6 +43,10 @@ func (m *Minimal) StandardBridge() *dsl.StandardBridge { return dsl.NewStandardBridge(m.T, m.L2Chain, nil, m.L1EL) } +func (m *Minimal) DisputeGameFactory() *proofs.DisputeGameFactory { + return proofs.NewDisputeGameFactory(m.T, m.L1Network, m.L1EL.EthClient(), m.L2Chain.DisputeGameFactoryProxyAddr(), nil) +} + func WithMinimal() stack.CommonOption { return stack.MakeCommon(sysgo.DefaultMinimalSystem(&sysgo.DefaultMinimalSystemIDs{})) } diff --git a/op-devstack/sysgo/system.go b/op-devstack/sysgo/system.go index 92b818b0a373e..8ee74cbf0802b 100644 --- a/op-devstack/sysgo/system.go +++ b/op-devstack/sysgo/system.go @@ -2,7 +2,7 @@ package sysgo import ( "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" - "github.com/ethereum-optimism/optimism/op-chain-ops/interopgen" + "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer" "github.com/ethereum-optimism/optimism/op-devstack/stack" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -332,7 +332,7 @@ func defaultSuperProofsSystem(dest *DefaultInteropSystemIDs, deployerOpts ...Dep WithCommons(ids.L1.ChainID()), WithPrefundedL2(ids.L1.ChainID(), ids.L2A.ChainID()), WithPrefundedL2(ids.L1.ChainID(), ids.L2B.ChainID()), - WithDevFeatureBitmap(interopgen.OptimismPortalInteropDevFlag), + WithDevFeatureBitmap(deployer.OptimismPortalInteropDevFlag), }, deployerOpts...)...)) opt.Add(WithL1Nodes(ids.L1EL, ids.L1CL)) diff --git a/op-service/txintent/bindings/DisputeGameFactory.go b/op-service/txintent/bindings/DisputeGameFactory.go index a04a8ca0b5b31..553120b2039f4 100644 --- a/op-service/txintent/bindings/DisputeGameFactory.go +++ b/op-service/txintent/bindings/DisputeGameFactory.go @@ -30,6 +30,7 @@ type DisputeGameFactory struct { GameCount func() TypedCall[*big.Int] `sol:"gameCount"` GameAtIndex func(index *big.Int) TypedCall[DisputeGame] `sol:"gameAtIndex"` GameImpls func(gameType uint32) TypedCall[common.Address] `sol:"gameImpls"` + GameArgs func(gameType uint32) TypedCall[[]byte] `sol:"gameArgs"` Games func(gameType uint32, rootClaim common.Hash, extraData []byte) TypedCall[struct { Proxy common.Address Timestamp uint64 From 87cce4b74688bd8ea4d70ee6ed84d74b74c29e38 Mon Sep 17 00:00:00 2001 From: inphi Date: Tue, 7 Oct 2025 19:32:04 -0400 Subject: [PATCH 2/2] add missing skip --- op-acceptance-tests/tests/base/disputegame_v2/smoke_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/op-acceptance-tests/tests/base/disputegame_v2/smoke_test.go b/op-acceptance-tests/tests/base/disputegame_v2/smoke_test.go index c6e8d20ccd37e..3824d1e62e14d 100644 --- a/op-acceptance-tests/tests/base/disputegame_v2/smoke_test.go +++ b/op-acceptance-tests/tests/base/disputegame_v2/smoke_test.go @@ -9,6 +9,7 @@ import ( ) func TestSmoke(gt *testing.T) { + gt.Skip("TODO(#17257): Re-enable once opcm.deploy supports v2 dispute games") t := devtest.SerialT(gt) sys := presets.NewMinimal(t) require := t.Require()