diff --git a/packages/contracts-bedrock/interfaces/L1/IOPContractsManager.sol b/packages/contracts-bedrock/interfaces/L1/IOPContractsManager.sol index b6e5a82ece20e..fb3b4e92b80b2 100644 --- a/packages/contracts-bedrock/interfaces/L1/IOPContractsManager.sol +++ b/packages/contracts-bedrock/interfaces/L1/IOPContractsManager.sol @@ -10,7 +10,7 @@ import { IDelayedWETH } from "interfaces/dispute/IDelayedWETH.sol"; import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol"; import { IAddressManager } from "interfaces/legacy/IAddressManager.sol"; import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; -import { IDelayedWETH } from "interfaces/dispute/IDelayedWETH.sol"; +import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol"; import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol"; import { IPermissionedDisputeGame } from "interfaces/dispute/IPermissionedDisputeGame.sol"; @@ -166,6 +166,13 @@ interface IOPContractsManager { /// @param upgrader Address that initiated the upgrade event Upgraded(uint256 indexed l2ChainId, ISystemConfig indexed systemConfig, address indexed upgrader); + /// @notice Emitted when a new game type is added to a chain + /// @param l2ChainId Chain ID of the chain + /// @param gameType Type of the game being added + /// @param disputeGame Address of the deployed dispute game + /// @param delayedWETH Address of the WETH contract used by the game + event GameTypeAdded(uint256 indexed l2ChainId, GameType indexed gameType, IDisputeGame disputeGame, IDelayedWETH delayedWETH); + // -------- Errors -------- error BytesArrayTooLong(); diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 7ec3000cb1886..411e06f3841ea 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -16,12 +16,12 @@ "sourceCodeHash": "0xf9ba98657dc235355146e381b654fe3ed766feb7cd87636ec0c9d4c6dd3e1973" }, "src/L1/OPContractsManager.sol": { - "initCodeHash": "0x89331280649debc424f9dd9f8a0afa877fd5ad122482e8dace21abde2929698d", - "sourceCodeHash": "0xd9e68a8adc202cc6d794fd3c9812013eb97e43a1cad661a55c9030d8b68e0025" + "initCodeHash": "0x4c48e78c30304497622a26c4b4f757f94520181a4d8835cc9ef63b1462735adc", + "sourceCodeHash": "0x8048aa568ddfb5e9138277db5a5fea5fc16ce93ec81e91d65c08be241992aabf" }, "src/L1/OPContractsManagerInterop.sol": { - "initCodeHash": "0xaf32c9ce79005193fb956088c0c8bda5d367ad869b989cb0e81c21339b93ce33", - "sourceCodeHash": "0x519c9a5bae5da6ea8280873fea5fa244dc55b435f48f731528fbe37b639d9333" + "initCodeHash": "0xb0173d4c602250ef27af1f9e9f337d13c014e2cf5b83c31dc20e8db81c011366", + "sourceCodeHash": "0x0ba9c63e3f00dab87be058fd0091f19c51faeafd24609bc13667214796bcc106" }, "src/L1/OptimismPortal2.sol": { "initCodeHash": "0x2cc5776c92d6cb154aa3d9897c476deaf49d98dc81493fabaea72987b9588853", diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index fc3ad7430254b..5c9c055936a2a 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -144,9 +144,9 @@ contract OPContractsManager is ISemver { // -------- Constants and Variables -------- - /// @custom:semver 1.1.0 + /// @custom:semver 1.2.0 function version() public pure virtual returns (string memory) { - return "1.1.0"; + return "1.2.0"; } /// @notice Address of the SuperchainConfig contract shared by all chains. @@ -198,6 +198,15 @@ contract OPContractsManager is ISemver { /// @param upgrader Address that initiated the upgrade event Upgraded(uint256 indexed l2ChainId, ISystemConfig indexed systemConfig, address indexed upgrader); + /// @notice Emitted when a new game type is added to a chain + /// @param l2ChainId Chain ID of the chain + /// @param gameType Type of the game being added + /// @param disputeGame Address of the deployed dispute game + /// @param delayedWETH Address of the WETH contract used by the game + event GameTypeAdded( + uint256 indexed l2ChainId, GameType indexed gameType, IDisputeGame disputeGame, IDelayedWETH delayedWETH + ); + // -------- Errors -------- /// @notice Thrown when an address other than the upgrade controller calls the setRC function. @@ -707,6 +716,11 @@ contract OPContractsManager is ISemver { IDisputeGameFactory dgf = getDisputeGameFactory(gameConfig.systemConfig); setDGFImplementation(dgf, gameConfig.disputeGameType, IDisputeGame(address(outputs[i].faultDisputeGame))); dgf.setInitBond(gameConfig.disputeGameType, gameConfig.initialBond); + + // Emit event for the newly added game type + emit GameTypeAdded( + l2ChainId, gameConfig.disputeGameType, outputs[i].faultDisputeGame, outputs[i].delayedWETH + ); } return outputs; diff --git a/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol b/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol index c448df06d8675..c7122c98eb528 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol @@ -13,9 +13,9 @@ import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol"; import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; contract OPContractsManagerInterop is OPContractsManager { - /// @custom:semver +interop.3 + /// @custom:semver +interop.4 function version() public pure override returns (string memory) { - return string.concat(super.version(), "+interop.3"); + return string.concat(super.version(), "+interop.4"); } constructor( diff --git a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol index 95a25e2904d55..e64be16e0ff5e 100644 --- a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol +++ b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol @@ -25,6 +25,8 @@ import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol"; import { IPreimageOracle } from "interfaces/cannon/IPreimageOracle.sol"; import { IPermissionedDisputeGame } from "interfaces/dispute/IPermissionedDisputeGame.sol"; import { IDelayedWETH } from "interfaces/dispute/IDelayedWETH.sol"; +import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol"; +import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { IOPContractsManager } from "interfaces/L1/IOPContractsManager.sol"; @@ -526,6 +528,10 @@ contract OPContractsManager_AddGameType_Test is Test { IOPContractsManager.DeployOutput internal chainDeployOutput; + event GameTypeAdded( + uint256 indexed l2ChainId, GameType indexed gameType, IDisputeGame disputeGame, IDelayedWETH delayedWETH + ); + function setUp() public { ISuperchainConfig superchainConfigProxy = ISuperchainConfig(makeAddr("superchainConfig")); IProtocolVersions protocolVersionsProxy = IProtocolVersions(makeAddr("protocolVersions")); @@ -697,6 +703,13 @@ contract OPContractsManager_AddGameType_Test is Test { IOPContractsManager.AddGameInput[] memory inputs = new IOPContractsManager.AddGameInput[](1); inputs[0] = input; + uint256 l2ChainId = IFaultDisputeGame( + address(IDisputeGameFactory(input.systemConfig.disputeGameFactory()).gameImpls(GameType.wrap(1))) + ).l2ChainId(); + + // Expect the GameTypeAdded event to be emitted. + vm.expectEmit(true, true, false, false, address(this)); + emit GameTypeAdded(l2ChainId, input.disputeGameType, IDisputeGame(payable(address(0))), IDelayedWETH(payable(address(0)))); (bool success, bytes memory rawGameOut) = address(opcm).delegatecall(abi.encodeCall(IOPContractsManager.addGameType, (inputs))); assertTrue(success, "addGameType failed");