diff --git a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol index 9e688f29ae6df..56e6b6feba3d9 100644 --- a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol @@ -64,20 +64,6 @@ import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; contract Deploy is Deployer { using stdJson for string; - /// @notice FaultDisputeGameParams is a struct that contains the parameters necessary to call - /// the function _setFaultGameImplementation. This struct exists because the EVM needs - /// to finally adopt PUSHN and get rid of stack too deep once and for all. - /// Someday we will look back and laugh about stack too deep, today is not that day. - struct FaultDisputeGameParams { - IAnchorStateRegistry anchorStateRegistry; - IDelayedWETH weth; - GameType gameType; - Claim absolutePrestate; - IBigStepper faultVm; - uint256 maxGameDepth; - Duration maxClockDuration; - } - //////////////////////////////////////////////////////////////// // Modifiers // //////////////////////////////////////////////////////////////// @@ -871,14 +857,17 @@ contract Deploy is Deployer { // Set the Cannon FaultDisputeGame implementation in the factory. _setFaultGameImplementation({ _factory: factory, - _params: FaultDisputeGameParams({ - anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), - weth: weth, + _params: IFaultDisputeGame.GameConstructorParams({ gameType: GameTypes.CANNON, absolutePrestate: loadMipsAbsolutePrestate(), - faultVm: IBigStepper(mustGetAddress("Mips")), maxGameDepth: cfg.faultGameMaxDepth(), - maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration())) + splitDepth: cfg.faultGameSplitDepth(), + clockExtension: Duration.wrap(uint64(cfg.faultGameClockExtension())), + maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), + vm: IBigStepper(mustGetAddress("Mips")), + weth: weth, + anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + l2ChainId: cfg.l2ChainID() }) }); } @@ -892,15 +881,18 @@ contract Deploy is Deployer { Claim outputAbsolutePrestate = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate())); _setFaultGameImplementation({ _factory: factory, - _params: FaultDisputeGameParams({ - anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), - weth: weth, + _params: IFaultDisputeGame.GameConstructorParams({ gameType: GameTypes.ALPHABET, absolutePrestate: outputAbsolutePrestate, - faultVm: IBigStepper(new AlphabetVM(outputAbsolutePrestate, IPreimageOracle(mustGetAddress("PreimageOracle")))), // The max depth for the alphabet trace is always 3. Add 1 because split depth is fully inclusive. maxGameDepth: cfg.faultGameSplitDepth() + 3 + 1, - maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration())) + splitDepth: cfg.faultGameSplitDepth(), + clockExtension: Duration.wrap(uint64(cfg.faultGameClockExtension())), + maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), + vm: IBigStepper(new AlphabetVM(outputAbsolutePrestate, IPreimageOracle(mustGetAddress("PreimageOracle")))), + weth: weth, + anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + l2ChainId: cfg.l2ChainID() }) }); } @@ -925,23 +917,26 @@ contract Deploy is Deployer { ); _setFaultGameImplementation({ _factory: factory, - _params: FaultDisputeGameParams({ - anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), - weth: weth, + _params: IFaultDisputeGame.GameConstructorParams({ gameType: GameTypes.FAST, absolutePrestate: outputAbsolutePrestate, - faultVm: IBigStepper(new AlphabetVM(outputAbsolutePrestate, fastOracle)), // The max depth for the alphabet trace is always 3. Add 1 because split depth is fully inclusive. maxGameDepth: cfg.faultGameSplitDepth() + 3 + 1, - maxClockDuration: Duration.wrap(0) // Resolvable immediately - }) + splitDepth: cfg.faultGameSplitDepth(), + clockExtension: Duration.wrap(uint64(cfg.faultGameClockExtension())), + maxClockDuration: Duration.wrap(0), // Resolvable immediately + vm: IBigStepper(new AlphabetVM(outputAbsolutePrestate, fastOracle)), + weth: weth, + anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + l2ChainId: cfg.l2ChainID() + }) }); } /// @notice Sets the implementation for the given fault game type in the `DisputeGameFactory`. function _setFaultGameImplementation( IDisputeGameFactory _factory, - FaultDisputeGameParams memory _params + IFaultDisputeGame.GameConstructorParams memory _params ) internal { @@ -954,37 +949,19 @@ contract Deploy is Deployer { } uint32 rawGameType = GameType.unwrap(_params.gameType); - - // Redefine _param variable to avoid stack too deep error during compilation - FaultDisputeGameParams memory _params_ = _params; require( rawGameType != GameTypes.PERMISSIONED_CANNON.raw(), "Deploy: Permissioned Game should be deployed by OPCM" ); + _factory.setImplementation( - _params_.gameType, + _params.gameType, IDisputeGame( DeployUtils.create2AndSave({ _save: this, _salt: _implSalt(), _name: "FaultDisputeGame", _nick: string.concat("FaultDisputeGame_", vm.toString(rawGameType)), - _args: DeployUtils.encodeConstructor( - abi.encodeCall( - IFaultDisputeGame.__constructor__, - ( - _params_.gameType, - _params_.absolutePrestate, - _params_.maxGameDepth, - cfg.faultGameSplitDepth(), - Duration.wrap(uint64(cfg.faultGameClockExtension())), - _params_.maxClockDuration, - _params_.faultVm, - _params_.weth, - IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), - cfg.l2ChainID() - ) - ) - ) + _args: DeployUtils.encodeConstructor(abi.encodeCall(IFaultDisputeGame.__constructor__, (_params))) }) ) ); diff --git a/packages/contracts-bedrock/scripts/deploy/DeployDisputeGame.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployDisputeGame.s.sol index 153e4b65fdb4e..67893d2cb1314 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployDisputeGame.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployDisputeGame.s.sol @@ -270,19 +270,17 @@ contract DeployDisputeGame is Script { function deployDisputeGameImpl(DeployDisputeGameInput _dgi, DeployDisputeGameOutput _dgo) internal { // Shove the arguments into a struct to avoid stack-too-deep errors. - DisputeGameConstructorArgs memory args = DisputeGameConstructorArgs({ + IFaultDisputeGame.GameConstructorParams memory args = IFaultDisputeGame.GameConstructorParams({ gameType: GameType.wrap(uint32(_dgi.gameType())), absolutePrestate: Claim.wrap(_dgi.absolutePrestate()), maxGameDepth: _dgi.maxGameDepth(), splitDepth: _dgi.splitDepth(), clockExtension: Duration.wrap(uint64(_dgi.clockExtension())), maxClockDuration: Duration.wrap(uint64(_dgi.maxClockDuration())), - gameVm: IBigStepper(address(_dgi.vmAddress())), - delayedWethProxy: _dgi.delayedWethProxy(), - anchorStateRegistryProxy: _dgi.anchorStateRegistryProxy(), - l2ChainId: _dgi.l2ChainId(), - proposer: _dgi.proposer(), - challenger: _dgi.challenger() + vm: IBigStepper(address(_dgi.vmAddress())), + weth: _dgi.delayedWethProxy(), + anchorStateRegistry: _dgi.anchorStateRegistryProxy(), + l2ChainId: _dgi.l2ChainId() }); // PermissionedDisputeGame is used as the type here because it is a superset of @@ -294,23 +292,7 @@ contract DeployDisputeGame is Script { impl = IPermissionedDisputeGame( DeployUtils.create1({ _name: "FaultDisputeGame", - _args: DeployUtils.encodeConstructor( - abi.encodeCall( - IFaultDisputeGame.__constructor__, - ( - args.gameType, - args.absolutePrestate, - args.maxGameDepth, - args.splitDepth, - args.clockExtension, - args.maxClockDuration, - args.gameVm, - args.delayedWethProxy, - args.anchorStateRegistryProxy, - args.l2ChainId - ) - ) - ) + _args: DeployUtils.encodeConstructor(abi.encodeCall(IFaultDisputeGame.__constructor__, (args))) }) ); } else { @@ -318,23 +300,7 @@ contract DeployDisputeGame is Script { DeployUtils.create1({ _name: "PermissionedDisputeGame", _args: DeployUtils.encodeConstructor( - abi.encodeCall( - IPermissionedDisputeGame.__constructor__, - ( - args.gameType, - args.absolutePrestate, - args.maxGameDepth, - args.splitDepth, - args.clockExtension, - args.maxClockDuration, - args.gameVm, - args.delayedWethProxy, - args.anchorStateRegistryProxy, - args.l2ChainId, - args.proposer, - args.challenger - ) - ) + abi.encodeCall(IPermissionedDisputeGame.__constructor__, (args, _dgi.proposer(), _dgi.challenger())) ) }) ); diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/DeployUpgrade.s.sol b/packages/contracts-bedrock/scripts/upgrades/holocene/DeployUpgrade.s.sol index 8203e42b060c6..680c4bea12748 100644 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/DeployUpgrade.s.sol +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/DeployUpgrade.s.sol @@ -138,16 +138,18 @@ contract DeployUpgrade is Deployer { bytes memory constructorInput = abi.encodeCall( IFaultDisputeGame.__constructor__, ( - GameTypes.CANNON, - Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate())), - cfg.faultGameMaxDepth(), - cfg.faultGameSplitDepth(), - Duration.wrap(uint64(cfg.faultGameClockExtension())), - Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), - IBigStepper(mustGetAddress("MIPS")), - IDelayedWETH(payable(mustGetAddress("DelayedWETHProxyFDG"))), - IAnchorStateRegistry(mustGetAddress("AnchorStateRegistry")), - cfg.l2ChainID() + IFaultDisputeGame.GameConstructorParams({ + gameType: GameTypes.CANNON, + absolutePrestate: Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate())), + maxGameDepth: cfg.faultGameMaxDepth(), + splitDepth: cfg.faultGameSplitDepth(), + clockExtension: Duration.wrap(uint64(cfg.faultGameClockExtension())), + maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), + vm: IBigStepper(mustGetAddress("MIPS")), + weth: IDelayedWETH(payable(mustGetAddress("DelayedWETHProxyFDG"))), + anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistry")), + l2ChainId: cfg.l2ChainID() + }) ) ); @@ -197,16 +199,18 @@ contract DeployUpgrade is Deployer { bytes memory constructorInput = abi.encodeCall( IPermissionedDisputeGame.__constructor__, ( - GameTypes.PERMISSIONED_CANNON, - Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate())), - cfg.faultGameMaxDepth(), - cfg.faultGameSplitDepth(), - Duration.wrap(uint64(cfg.faultGameClockExtension())), - Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), - IBigStepper(mustGetAddress("MIPS")), - IDelayedWETH(payable(mustGetAddress("DelayedWETHProxyPDG"))), - IAnchorStateRegistry(mustGetAddress("AnchorStateRegistry")), - cfg.l2ChainID(), + IFaultDisputeGame.GameConstructorParams({ + gameType: GameTypes.PERMISSIONED_CANNON, + absolutePrestate: Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate())), + maxGameDepth: cfg.faultGameMaxDepth(), + splitDepth: cfg.faultGameSplitDepth(), + clockExtension: Duration.wrap(uint64(cfg.faultGameClockExtension())), + maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), + vm: IBigStepper(mustGetAddress("MIPS")), + weth: IDelayedWETH(payable(mustGetAddress("DelayedWETHProxyPDG"))), + anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistry")), + l2ChainId: cfg.l2ChainID() + }), cfg.l2OutputOracleProposer(), cfg.l2OutputOracleChallenger() ) diff --git a/packages/contracts-bedrock/snapshots/abi/FaultDisputeGame.json b/packages/contracts-bedrock/snapshots/abi/FaultDisputeGame.json index e1e59c38701cf..a2f02cce13bd8 100644 --- a/packages/contracts-bedrock/snapshots/abi/FaultDisputeGame.json +++ b/packages/contracts-bedrock/snapshots/abi/FaultDisputeGame.json @@ -2,54 +2,61 @@ { "inputs": [ { - "internalType": "GameType", - "name": "_gameType", - "type": "uint32" - }, - { - "internalType": "Claim", - "name": "_absolutePrestate", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_maxGameDepth", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_splitDepth", - "type": "uint256" - }, - { - "internalType": "Duration", - "name": "_clockExtension", - "type": "uint64" - }, - { - "internalType": "Duration", - "name": "_maxClockDuration", - "type": "uint64" - }, - { - "internalType": "contract IBigStepper", - "name": "_vm", - "type": "address" - }, - { - "internalType": "contract IDelayedWETH", - "name": "_weth", - "type": "address" - }, - { - "internalType": "contract IAnchorStateRegistry", - "name": "_anchorStateRegistry", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_l2ChainId", - "type": "uint256" + "components": [ + { + "internalType": "GameType", + "name": "gameType", + "type": "uint32" + }, + { + "internalType": "Claim", + "name": "absolutePrestate", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxGameDepth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "splitDepth", + "type": "uint256" + }, + { + "internalType": "Duration", + "name": "clockExtension", + "type": "uint64" + }, + { + "internalType": "Duration", + "name": "maxClockDuration", + "type": "uint64" + }, + { + "internalType": "contract IBigStepper", + "name": "vm", + "type": "address" + }, + { + "internalType": "contract IDelayedWETH", + "name": "weth", + "type": "address" + }, + { + "internalType": "contract IAnchorStateRegistry", + "name": "anchorStateRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "l2ChainId", + "type": "uint256" + } + ], + "internalType": "struct FaultDisputeGame.GameConstructorParams", + "name": "_params", + "type": "tuple" } ], "stateMutability": "nonpayable", diff --git a/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json b/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json index fd9737cc5842c..eebc4adf16ea5 100644 --- a/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json +++ b/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json @@ -2,54 +2,61 @@ { "inputs": [ { - "internalType": "GameType", - "name": "_gameType", - "type": "uint32" - }, - { - "internalType": "Claim", - "name": "_absolutePrestate", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_maxGameDepth", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_splitDepth", - "type": "uint256" - }, - { - "internalType": "Duration", - "name": "_clockExtension", - "type": "uint64" - }, - { - "internalType": "Duration", - "name": "_maxClockDuration", - "type": "uint64" - }, - { - "internalType": "contract IBigStepper", - "name": "_vm", - "type": "address" - }, - { - "internalType": "contract IDelayedWETH", - "name": "_weth", - "type": "address" - }, - { - "internalType": "contract IAnchorStateRegistry", - "name": "_anchorStateRegistry", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_l2ChainId", - "type": "uint256" + "components": [ + { + "internalType": "GameType", + "name": "gameType", + "type": "uint32" + }, + { + "internalType": "Claim", + "name": "absolutePrestate", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxGameDepth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "splitDepth", + "type": "uint256" + }, + { + "internalType": "Duration", + "name": "clockExtension", + "type": "uint64" + }, + { + "internalType": "Duration", + "name": "maxClockDuration", + "type": "uint64" + }, + { + "internalType": "contract IBigStepper", + "name": "vm", + "type": "address" + }, + { + "internalType": "contract IDelayedWETH", + "name": "weth", + "type": "address" + }, + { + "internalType": "contract IAnchorStateRegistry", + "name": "anchorStateRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "l2ChainId", + "type": "uint256" + } + ], + "internalType": "struct FaultDisputeGame.GameConstructorParams", + "name": "_params", + "type": "tuple" }, { "internalType": "address", diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 8bd5ea33f7729..32de3eeb7f332 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -164,8 +164,8 @@ "sourceCodeHash": "0x9cb0851b6e471461f2bb369bd72eef4cffe8a0d1345546608a2aa6795540211d" }, "src/dispute/FaultDisputeGame.sol": { - "initCodeHash": "0xa352179f5055232764aac6b66a3ff5a6b3bfae2101d20c077f714b0ed7e40eef", - "sourceCodeHash": "0x730eff9147294c115a0a53e7e75771bcc4a517beb48457140ab929a8d1510893" + "initCodeHash": "0x7441e418d3b4229f519c8c027f3fd7a5487206b833110b794cca104a1a2c73fe", + "sourceCodeHash": "0x8f4bf662fe8d56e9aabaa7742033880f0900cd6221c7711c1dbefe985a841104" }, "src/legacy/DeployerWhitelist.sol": { "initCodeHash": "0xf232863fde5cd65368bcb4a79b41b5a4a09c59ede5070f82fd3f13f681bea7d8", diff --git a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol index 2bd5ec67e96c2..6aad60e428396 100644 --- a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol @@ -86,6 +86,21 @@ contract FaultDisputeGame is Clone, ISemver { address counteredBy; } + /// @notice Parameters for creating a new FaultDisputeGame. We place this into a struct to + /// avoid stack-too-deep errors when compiling without the optimizer enabled. + struct GameConstructorParams { + GameType gameType; + Claim absolutePrestate; + uint256 maxGameDepth; + uint256 splitDepth; + Duration clockExtension; + Duration maxClockDuration; + IBigStepper vm; + IDelayedWETH weth; + IAnchorStateRegistry anchorStateRegistry; + uint256 l2ChainId; + } + //////////////////////////////////////////////////////////////// // Events // //////////////////////////////////////////////////////////////// @@ -146,8 +161,8 @@ contract FaultDisputeGame is Clone, ISemver { uint256 internal constant HEADER_BLOCK_NUMBER_INDEX = 8; /// @notice Semantic version. - /// @custom:semver 1.3.1-beta.7 - string public constant version = "1.3.1-beta.7"; + /// @custom:semver 1.3.1-beta.8 + string public constant version = "1.3.1-beta.8"; /// @notice The starting timestamp of the game Timestamp public createdAt; @@ -189,69 +204,52 @@ contract FaultDisputeGame is Clone, ISemver { /// @notice The latest finalized output root, serving as the anchor for output bisection. OutputRoot public startingOutputRoot; - /// @param _gameType The type ID of the game. - /// @param _absolutePrestate The absolute prestate of the instruction trace. - /// @param _maxGameDepth The maximum depth of bisection. - /// @param _splitDepth The final depth of the output bisection portion of the game. - /// @param _clockExtension The clock extension to perform when the remaining duration is less than the extension. - /// @param _maxClockDuration The maximum amount of time that may accumulate on a team's chess clock. - /// @param _vm An onchain VM that performs single instruction steps on an FPP trace. - /// @param _weth WETH contract for holding ETH. - /// @param _anchorStateRegistry The contract that stores the anchor state for each game type. - /// @param _l2ChainId Chain ID of the L2 network this contract argues about. - constructor( - GameType _gameType, - Claim _absolutePrestate, - uint256 _maxGameDepth, - uint256 _splitDepth, - Duration _clockExtension, - Duration _maxClockDuration, - IBigStepper _vm, - IDelayedWETH _weth, - IAnchorStateRegistry _anchorStateRegistry, - uint256 _l2ChainId - ) { + /// @param _params Parameters for creating a new FaultDisputeGame. + constructor(GameConstructorParams memory _params) { // The max game depth may not be greater than `LibPosition.MAX_POSITION_BITLEN - 1`. - if (_maxGameDepth > LibPosition.MAX_POSITION_BITLEN - 1) revert MaxDepthTooLarge(); + if (_params.maxGameDepth > LibPosition.MAX_POSITION_BITLEN - 1) revert MaxDepthTooLarge(); // The split depth plus one cannot be greater than or equal to the max game depth. We add // an additional depth to the split depth to avoid a bug in trace ancestor lookup. We know // that the case where the split depth is the max value for uint256 is equivalent to the // second check though we do need to check it explicitly to avoid an overflow. - if (_splitDepth == type(uint256).max || _splitDepth + 1 >= _maxGameDepth) revert InvalidSplitDepth(); + if (_params.splitDepth == type(uint256).max || _params.splitDepth + 1 >= _params.maxGameDepth) { + revert InvalidSplitDepth(); + } // The split depth cannot be 0 or 1 to stay in bounds of clock extension arithmetic. - if (_splitDepth < 2) revert InvalidSplitDepth(); + if (_params.splitDepth < 2) revert InvalidSplitDepth(); // The PreimageOracle challenge period must fit into uint64 so we can safely use it here. // Runtime check was added instead of changing the ABI since the contract is already // deployed in production. We perform the same check within the PreimageOracle for the // benefit of developers but also perform this check here defensively. - if (_vm.oracle().challengePeriod() > type(uint64).max) revert InvalidChallengePeriod(); + if (_params.vm.oracle().challengePeriod() > type(uint64).max) revert InvalidChallengePeriod(); // Determine the maximum clock extension which is either the split depth extension or the // maximum game depth extension depending on the configuration of these contracts. - uint256 splitDepthExtension = uint256(_clockExtension.raw()) * 2; - uint256 maxGameDepthExtension = uint256(_clockExtension.raw()) + uint256(_vm.oracle().challengePeriod()); + uint256 splitDepthExtension = uint256(_params.clockExtension.raw()) * 2; + uint256 maxGameDepthExtension = + uint256(_params.clockExtension.raw()) + uint256(_params.vm.oracle().challengePeriod()); uint256 maxClockExtension = Math.max(splitDepthExtension, maxGameDepthExtension); // The maximum clock extension must fit into a uint64. if (maxClockExtension > type(uint64).max) revert InvalidClockExtension(); // The maximum clock extension may not be greater than the maximum clock duration. - if (uint64(maxClockExtension) > _maxClockDuration.raw()) revert InvalidClockExtension(); + if (uint64(maxClockExtension) > _params.maxClockDuration.raw()) revert InvalidClockExtension(); // Set up initial game state. - GAME_TYPE = _gameType; - ABSOLUTE_PRESTATE = _absolutePrestate; - MAX_GAME_DEPTH = _maxGameDepth; - SPLIT_DEPTH = _splitDepth; - CLOCK_EXTENSION = _clockExtension; - MAX_CLOCK_DURATION = _maxClockDuration; - VM = _vm; - WETH = _weth; - ANCHOR_STATE_REGISTRY = _anchorStateRegistry; - L2_CHAIN_ID = _l2ChainId; + GAME_TYPE = _params.gameType; + ABSOLUTE_PRESTATE = _params.absolutePrestate; + MAX_GAME_DEPTH = _params.maxGameDepth; + SPLIT_DEPTH = _params.splitDepth; + CLOCK_EXTENSION = _params.clockExtension; + MAX_CLOCK_DURATION = _params.maxClockDuration; + VM = _params.vm; + WETH = _params.weth; + ANCHOR_STATE_REGISTRY = _params.anchorStateRegistry; + L2_CHAIN_ID = _params.l2ChainId; } /// @notice Initializes the contract. diff --git a/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol b/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol index 373498f55bfa6..de907695d0063 100644 --- a/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol @@ -5,14 +5,9 @@ pragma solidity 0.8.15; import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; // Libraries -import { GameType, Claim, Duration } from "src/dispute/lib/Types.sol"; +import { Claim } from "src/dispute/lib/Types.sol"; import { BadAuth } from "src/dispute/lib/Errors.sol"; -// Interfaces -import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; -import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; -import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; - /// @title PermissionedDisputeGame /// @notice PermissionedDisputeGame is a contract that inherits from `FaultDisputeGame`, and contains two roles: /// - The `challenger` role, which is allowed to challenge a dispute. @@ -36,44 +31,15 @@ contract PermissionedDisputeGame is FaultDisputeGame { _; } - /// @param _gameType The type ID of the game. - /// @param _absolutePrestate The absolute prestate of the instruction trace. - /// @param _maxGameDepth The maximum depth of bisection. - /// @param _splitDepth The final depth of the output bisection portion of the game. - /// @param _clockExtension The clock extension to perform when the remaining duration is less than the extension. - /// @param _maxClockDuration The maximum amount of time that may accumulate on a team's chess clock. - /// @param _vm An onchain VM that performs single instruction steps on an FPP trace. - /// @param _weth WETH contract for holding ETH. - /// @param _anchorStateRegistry The contract that stores the anchor state for each game type. - /// @param _l2ChainId Chain ID of the L2 network this contract argues about. + /// @param _params Parameters for creating a new FaultDisputeGame. /// @param _proposer Address that is allowed to create instances of this contract. /// @param _challenger Address that is allowed to challenge instances of this contract. constructor( - GameType _gameType, - Claim _absolutePrestate, - uint256 _maxGameDepth, - uint256 _splitDepth, - Duration _clockExtension, - Duration _maxClockDuration, - IBigStepper _vm, - IDelayedWETH _weth, - IAnchorStateRegistry _anchorStateRegistry, - uint256 _l2ChainId, + GameConstructorParams memory _params, address _proposer, address _challenger ) - FaultDisputeGame( - _gameType, - _absolutePrestate, - _maxGameDepth, - _splitDepth, - _clockExtension, - _maxClockDuration, - _vm, - _weth, - _anchorStateRegistry, - _l2ChainId - ) + FaultDisputeGame(_params) { PROPOSER = _proposer; CHALLENGER = _challenger; diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol b/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol index 8c5bac02e9ba8..a188063de54af 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol @@ -26,6 +26,19 @@ interface IFaultDisputeGame is IDisputeGame { address counteredBy; } + struct GameConstructorParams { + GameType gameType; + Claim absolutePrestate; + uint256 maxGameDepth; + uint256 splitDepth; + Duration clockExtension; + Duration maxClockDuration; + IBigStepper vm; + IDelayedWETH weth; + IAnchorStateRegistry anchorStateRegistry; + uint256 l2ChainId; + } + error AlreadyInitialized(); error AnchorRootNotFound(); error BlockNumberMatches(); @@ -113,17 +126,5 @@ interface IFaultDisputeGame is IDisputeGame { function vm() external view returns (IBigStepper vm_); function weth() external view returns (IDelayedWETH weth_); - function __constructor__( - GameType _gameType, - Claim _absolutePrestate, - uint256 _maxGameDepth, - uint256 _splitDepth, - Duration _clockExtension, - Duration _maxClockDuration, - IBigStepper _vm, - IDelayedWETH _weth, - IAnchorStateRegistry _anchorStateRegistry, - uint256 _l2ChainId - ) - external; + function __constructor__(GameConstructorParams memory _params) external; } diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol b/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol index c5a5a187ec129..08c9cd5aa2b31 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol @@ -2,12 +2,13 @@ pragma solidity ^0.8.0; import { Types } from "src/libraries/Types.sol"; -import { GameType, Claim, Position, Clock, Hash, Duration } from "src/dispute/lib/Types.sol"; +import { Claim, Position, Clock, Hash, Duration } from "src/dispute/lib/Types.sol"; import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; interface IPermissionedDisputeGame is IDisputeGame { struct ClaimData { @@ -120,16 +121,7 @@ interface IPermissionedDisputeGame is IDisputeGame { function challenger() external view returns (address challenger_); function __constructor__( - GameType _gameType, - Claim _absolutePrestate, - uint256 _maxGameDepth, - uint256 _splitDepth, - Duration _clockExtension, - Duration _maxClockDuration, - IBigStepper _vm, - IDelayedWETH _weth, - IAnchorStateRegistry _anchorStateRegistry, - uint256 _l2ChainId, + IFaultDisputeGame.GameConstructorParams memory _params, address _proposer, address _challenger ) diff --git a/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol index 70aad007e4021..df820bcb3cc1c 100644 --- a/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol @@ -73,16 +73,18 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init { abi.encodeCall( IFaultDisputeGame.__constructor__, ( - GAME_TYPE, - absolutePrestate, - 2 ** 3, - 2 ** 2, - Duration.wrap(3 hours), - Duration.wrap(3.5 days), - _vm, - delayedWeth, - anchorStateRegistry, - 10 + IFaultDisputeGame.GameConstructorParams({ + gameType: GAME_TYPE, + absolutePrestate: absolutePrestate, + maxGameDepth: 2 ** 3, + splitDepth: 2 ** 2, + clockExtension: Duration.wrap(3 hours), + maxClockDuration: Duration.wrap(3.5 days), + vm: _vm, + weth: delayedWeth, + anchorStateRegistry: anchorStateRegistry, + l2ChainId: 10 + }) ) ) ) @@ -154,16 +156,18 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { abi.encodeCall( IFaultDisputeGame.__constructor__, ( - GAME_TYPE, - absolutePrestate, - _maxGameDepth, - _maxGameDepth + 1, - Duration.wrap(3 hours), - Duration.wrap(3.5 days), - alphabetVM, - IDelayedWETH(payable(address(0))), - IAnchorStateRegistry(address(0)), - 10 + IFaultDisputeGame.GameConstructorParams({ + gameType: GAME_TYPE, + absolutePrestate: absolutePrestate, + maxGameDepth: _maxGameDepth, + splitDepth: _maxGameDepth + 1, + clockExtension: Duration.wrap(3 hours), + maxClockDuration: Duration.wrap(3.5 days), + vm: alphabetVM, + weth: IDelayedWETH(payable(address(0))), + anchorStateRegistry: IAnchorStateRegistry(address(0)), + l2ChainId: 10 + }) ) ) ) @@ -196,16 +200,18 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { abi.encodeCall( IFaultDisputeGame.__constructor__, ( - GAME_TYPE, - absolutePrestate, - 2 ** 3, - 2 ** 2, - Duration.wrap(3 hours), - Duration.wrap(3.5 days), - alphabetVM, - IDelayedWETH(payable(address(0))), - IAnchorStateRegistry(address(0)), - 10 + IFaultDisputeGame.GameConstructorParams({ + gameType: GAME_TYPE, + absolutePrestate: absolutePrestate, + maxGameDepth: 2 ** 3, + splitDepth: 2 ** 2, + clockExtension: Duration.wrap(3 hours), + maxClockDuration: Duration.wrap(3.5 days), + vm: alphabetVM, + weth: IDelayedWETH(payable(address(0))), + anchorStateRegistry: IAnchorStateRegistry(address(0)), + l2ChainId: 10 + }) ) ) ) @@ -234,16 +240,18 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { abi.encodeCall( IFaultDisputeGame.__constructor__, ( - GAME_TYPE, - absolutePrestate, - maxGameDepth, - _splitDepth, - Duration.wrap(3 hours), - Duration.wrap(3.5 days), - alphabetVM, - IDelayedWETH(payable(address(0))), - IAnchorStateRegistry(address(0)), - 10 + IFaultDisputeGame.GameConstructorParams({ + gameType: GAME_TYPE, + absolutePrestate: absolutePrestate, + maxGameDepth: maxGameDepth, + splitDepth: _splitDepth, + clockExtension: Duration.wrap(3 hours), + maxClockDuration: Duration.wrap(3.5 days), + vm: alphabetVM, + weth: IDelayedWETH(payable(address(0))), + anchorStateRegistry: IAnchorStateRegistry(address(0)), + l2ChainId: 10 + }) ) ) ) @@ -272,16 +280,18 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { abi.encodeCall( IFaultDisputeGame.__constructor__, ( - GAME_TYPE, - absolutePrestate, - 2 ** 3, - _splitDepth, - Duration.wrap(3 hours), - Duration.wrap(3.5 days), - alphabetVM, - IDelayedWETH(payable(address(0))), - IAnchorStateRegistry(address(0)), - 10 + IFaultDisputeGame.GameConstructorParams({ + gameType: GAME_TYPE, + absolutePrestate: absolutePrestate, + maxGameDepth: 2 ** 3, + splitDepth: _splitDepth, + clockExtension: Duration.wrap(3 hours), + maxClockDuration: Duration.wrap(3.5 days), + vm: alphabetVM, + weth: IDelayedWETH(payable(address(0))), + anchorStateRegistry: IAnchorStateRegistry(address(0)), + l2ChainId: 10 + }) ) ) ) @@ -318,16 +328,18 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { abi.encodeCall( IFaultDisputeGame.__constructor__, ( - GAME_TYPE, - absolutePrestate, - 16, - 8, - Duration.wrap(_clockExtension), - Duration.wrap(_maxClockDuration), - alphabetVM, - IDelayedWETH(payable(address(0))), - IAnchorStateRegistry(address(0)), - 10 + IFaultDisputeGame.GameConstructorParams({ + gameType: GAME_TYPE, + absolutePrestate: absolutePrestate, + maxGameDepth: 16, + splitDepth: 8, + clockExtension: Duration.wrap(_clockExtension), + maxClockDuration: Duration.wrap(_maxClockDuration), + vm: alphabetVM, + weth: IDelayedWETH(payable(address(0))), + anchorStateRegistry: IAnchorStateRegistry(address(0)), + l2ChainId: 10 + }) ) ) ) diff --git a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol index 99b70b9c6dffb..20c45bf44de10 100644 --- a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol @@ -17,6 +17,7 @@ import "src/dispute/lib/Errors.sol"; import { IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; import { IPermissionedDisputeGame } from "src/dispute/interfaces/IPermissionedDisputeGame.sol"; +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; contract PermissionedDisputeGame_Init is DisputeGameFactory_Init { /// @dev The type of the game being tested. @@ -67,16 +68,18 @@ contract PermissionedDisputeGame_Init is DisputeGameFactory_Init { abi.encodeCall( IPermissionedDisputeGame.__constructor__, ( - GAME_TYPE, - absolutePrestate, - 2 ** 3, - 2 ** 2, - Duration.wrap(3 hours), - Duration.wrap(3.5 days), - _vm, - _weth, - anchorStateRegistry, - 10, + IFaultDisputeGame.GameConstructorParams({ + gameType: GAME_TYPE, + absolutePrestate: absolutePrestate, + maxGameDepth: 2 ** 3, + splitDepth: 2 ** 2, + clockExtension: Duration.wrap(3 hours), + maxClockDuration: Duration.wrap(3.5 days), + vm: _vm, + weth: _weth, + anchorStateRegistry: anchorStateRegistry, + l2ChainId: 10 + }), PROPOSER, CHALLENGER )