diff --git a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol index f103db0053e..e175104ef75 100644 --- a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol +++ b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol @@ -163,23 +163,16 @@ contract OPContractsManager_Upgrade_Harness is CommonTest { // Artifacts encoded as an address. l2ChainId = uint256(uint160(address(artifacts.mustGetAddress("L2ChainId")))); - delayedWETHPermissionedGameProxy = - IDelayedWETH(payable(artifacts.mustGetAddress("PermissionedDelayedWETHProxy"))); - permissionedDisputeGame = IPermissionedDisputeGame(address(artifacts.mustGetAddress("PermissionedDisputeGame"))); IDisputeGameFactory dgf = IDisputeGameFactory(address(artifacts.mustGetAddress("DisputeGameFactoryProxy"))); - faultDisputeGame = IFaultDisputeGame(address(dgf.gameImpls(GameTypes.CANNON))); - delayedWeth = faultDisputeGame.weth(); // Grab the pre-upgrade state. Use getGameImplPrestate to handle both v1 and v2 // dispute games (v1 stores prestate on game impl, v2 stores it in gameArgs). preUpgradeState = PreUpgradeState({ - cannonAbsolutePrestate: DisputeGames.getGameImplPrestate(disputeGameFactory, GameTypes.CANNON), - permissionedAbsolutePrestate: DisputeGames.getGameImplPrestate( - disputeGameFactory, GameTypes.PERMISSIONED_CANNON - ), - cannonKonaAbsolutePrestate: DisputeGames.getGameImplPrestate(disputeGameFactory, GameTypes.CANNON_KONA), - permissionlessWethProxy: delayedWeth, - permissionedCannonWethProxy: delayedWETHPermissionedGameProxy + cannonAbsolutePrestate: DisputeGames.getGameImplPrestate(dgf, GameTypes.CANNON), + permissionedAbsolutePrestate: DisputeGames.getGameImplPrestate(dgf, GameTypes.PERMISSIONED_CANNON), + cannonKonaAbsolutePrestate: DisputeGames.getGameImplPrestate(dgf, GameTypes.CANNON_KONA), + permissionlessWethProxy: DisputeGames.getGameImplDelayedWeth(dgf, GameTypes.CANNON), + permissionedCannonWethProxy: DisputeGames.getGameImplDelayedWeth(dgf, GameTypes.PERMISSIONED_CANNON) }); // Since this superchainConfig is already at the expected reinitializer version... @@ -397,11 +390,19 @@ contract OPContractsManager_Upgrade_Harness is CommonTest { vm.assertEq(blockhash(block.number - 1), game.l1Head().raw()); if (gt.raw() == GameTypes.PERMISSIONED_CANNON.raw()) { - vm.assertEq(address(preUpgradeState.permissionedCannonWethProxy), address(game.weth())); + vm.assertEq( + address(preUpgradeState.permissionedCannonWethProxy), + address(game.weth()), + "Incorrect permissioned WETH" + ); vm.assertEq(_challenger, game.challenger()); vm.assertEq(_proposer, game.proposer()); } else { - vm.assertEq(address(preUpgradeState.permissionlessWethProxy), address(game.weth())); + vm.assertEq( + address(preUpgradeState.permissionlessWethProxy), + address(game.weth()), + "Incorrect permissionless WETH" + ); } } @@ -1428,8 +1429,10 @@ contract OPContractsManager_Upgrade_Test is OPContractsManager_Upgrade_Harness { disputeGameFactory, GameTypes.PERMISSIONED_CANNON ), cannonKonaAbsolutePrestate: DisputeGames.getGameImplPrestate(disputeGameFactory, GameTypes.CANNON_KONA), - permissionlessWethProxy: delayedWeth, - permissionedCannonWethProxy: delayedWETHPermissionedGameProxy + permissionlessWethProxy: DisputeGames.getGameImplDelayedWeth(disputeGameFactory, GameTypes.CANNON), + permissionedCannonWethProxy: DisputeGames.getGameImplDelayedWeth( + disputeGameFactory, GameTypes.PERMISSIONED_CANNON + ) }); } diff --git a/packages/contracts-bedrock/test/setup/DisputeGames.sol b/packages/contracts-bedrock/test/setup/DisputeGames.sol index 6268a5bc92f..e71b17ca4b7 100644 --- a/packages/contracts-bedrock/test/setup/DisputeGames.sol +++ b/packages/contracts-bedrock/test/setup/DisputeGames.sol @@ -13,6 +13,7 @@ import { LibGameArgs } from "src/dispute/lib/LibGameArgs.sol"; // Interfaces import "../../interfaces/dispute/IDisputeGame.sol"; +import "../../interfaces/dispute/IDelayedWETH.sol"; import "../../interfaces/dispute/IDisputeGameFactory.sol"; import { IFaultDisputeGame } from "../../interfaces/dispute/IFaultDisputeGame.sol"; import { IPermissionedDisputeGame } from "../../interfaces/dispute/IPermissionedDisputeGame.sol"; @@ -154,6 +155,35 @@ library DisputeGames { } } + /// @notice Gets the DelayedWETH for a game type, handling both v1 and v2 dispute games. + /// V1 games store the prestate on the game implementation, v2 games store it in gameArgs. + /// Returns address(0) if no implementation exists for the game type. + /// @param _dgf The dispute game factory. + /// @param _gameType The game type to get the DelayedWETH for. + /// @return delayedWeth_ The delayedWETH address. + function getGameImplDelayedWeth( + IDisputeGameFactory _dgf, + GameType _gameType + ) + internal + view + returns (IDelayedWETH delayedWeth_) + { + // Return zero if no implementation exists for this game type + address gameImpl = address(_dgf.gameImpls(_gameType)); + if (gameImpl == address(0)) { + return IDelayedWETH(payable(address(0))); + } + + (bool gameArgsExist, bytes memory gameArgsData) = _getGameArgs(_dgf, _gameType); + if (gameArgsExist) { + LibGameArgs.GameArgs memory gameArgs = LibGameArgs.decode(gameArgsData); + delayedWeth_ = IDelayedWETH(payable(gameArgs.weth)); + } else { + delayedWeth_ = IFaultDisputeGame(gameImpl).weth(); + } + } + function mockGameImplPrestate(IDisputeGameFactory _dgf, GameType _gameType, bytes32 _prestate) internal { bytes memory value = abi.encodePacked(_prestate); _mockGameArg(_dgf, _gameType, GameArg.PRESTATE, value); diff --git a/packages/contracts-bedrock/test/setup/ForkLive.s.sol b/packages/contracts-bedrock/test/setup/ForkLive.s.sol index c59a3feafb6..be371195255 100644 --- a/packages/contracts-bedrock/test/setup/ForkLive.s.sol +++ b/packages/contracts-bedrock/test/setup/ForkLive.s.sol @@ -32,7 +32,6 @@ import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; import { IOPContractsManager } from "interfaces/L1/IOPContractsManager.sol"; import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol"; -import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol"; import { IETHLockbox } from "interfaces/L1/IETHLockbox.sol"; import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; import { IOPContractsManagerUpgrader } from "interfaces/L1/IOPContractsManager.sol"; @@ -179,15 +178,22 @@ contract ForkLive is Deployer, StdAssertions, FeatureFlags { IDisputeGameFactory(artifacts.mustGetAddress("DisputeGameFactoryProxy")); // The PermissionedDisputeGame and PermissionedDelayedWETHProxy are not listed in the registry for OP, so we - // look it up onchain - IFaultDisputeGame permissionedDisputeGame = - IFaultDisputeGame(address(disputeGameFactory.gameImpls(GameTypes.PERMISSIONED_CANNON))); - artifacts.save("PermissionedDisputeGame", address(permissionedDisputeGame)); - artifacts.save("PermissionedDelayedWETHProxy", address(permissionedDisputeGame.weth())); - - // The SR seems out-of-date, so pull the DelayedWETH addresses from the PermissionedDisputeGame. - artifacts.save("DelayedWETHProxy", address(permissionedDisputeGame.weth())); - artifacts.save("DelayedWETHImpl", EIP1967Helper.getImplementation(address(permissionedDisputeGame.weth()))); + // look it up onchain. + address permissionedGameImpl = address(disputeGameFactory.gameImpls(GameTypes.PERMISSIONED_CANNON)); + artifacts.save("PermissionedDisputeGame", permissionedGameImpl); + + // Get DelayedWETH for PERMISSIONED games + IDelayedWETH permissionedDelayedWeth = + DisputeGames.getGameImplDelayedWeth(disputeGameFactory, GameTypes.PERMISSIONED_CANNON); + artifacts.save("PermissionedDelayedWETHProxy", address(permissionedDelayedWeth)); + + // Get DelayedWETH for PERMISSIONLESS games (CANNON) + IDelayedWETH permissionlessDelayedWeth = + DisputeGames.getGameImplDelayedWeth(disputeGameFactory, GameTypes.CANNON); + + // The SR seems out-of-date, so pull the DelayedWETH addresses from the games. + artifacts.save("DelayedWETHProxy", address(permissionlessDelayedWeth)); + artifacts.save("DelayedWETHImpl", EIP1967Helper.getImplementation(address(permissionlessDelayedWeth))); } /// @notice Calls to the Deploy.s.sol contract etched by Setup.sol to a deterministic address, sets up the