diff --git a/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol index 88e361a80b459..70aad007e4021 100644 --- a/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol @@ -449,6 +449,17 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { gameProxy.initialize(); } + /// @dev Tests that startingOutputRoot and it's getters are set correctly. + function test_startingOutputRootGetters_succeeds() public view { + (Hash root, uint256 l2BlockNumber) = gameProxy.startingOutputRoot(); + (Hash anchorRoot, uint256 anchorRootBlockNumber) = anchorStateRegistry.anchors(GAME_TYPE); + + assertEq(gameProxy.startingBlockNumber(), l2BlockNumber); + assertEq(gameProxy.startingBlockNumber(), anchorRootBlockNumber); + assertEq(Hash.unwrap(gameProxy.startingRootHash()), Hash.unwrap(root)); + assertEq(Hash.unwrap(gameProxy.startingRootHash()), Hash.unwrap(anchorRoot)); + } + /// @dev Tests that the user cannot control the first 4 bytes of the CWIA data, disallowing them to control the /// entrypoint when no calldata is provided to a call. function test_cwiaCalldata_userCannotControlSelector_succeeds() public { @@ -1986,6 +1997,18 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { assertEq(datLen, expectedLen); } + /// @dev Tests that if the game is not in progress, querying of `getChallengerDuration` reverts + function test_getChallengerDuration_gameNotInProgress_reverts() public { + // resolve the game + vm.warp(block.timestamp + gameProxy.maxClockDuration().raw()); + + gameProxy.resolveClaim(0, 0); + gameProxy.resolve(); + + vm.expectRevert(GameNotInProgress.selector); + gameProxy.getChallengerDuration(1); + } + /// @dev Static unit test asserting that resolveClaim isn't possible if there's time /// left for a counter. function test_resolution_lastSecondDisputes_succeeds() public { diff --git a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol index 698d8a0bd1f4a..99b70b9c6dffb 100644 --- a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol @@ -198,6 +198,61 @@ contract PermissionedDisputeGame_Test is PermissionedDisputeGame_Init { vm.stopPrank(); } + /// @dev Tests that step works properly. + function test_step_succeeds() public { + // Give the test contract some ether + vm.deal(CHALLENGER, 1_000 ether); + + vm.startPrank(CHALLENGER, CHALLENGER); + + // Make claims all the way down the tree. + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.attack{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(2); + gameProxy.attack{ value: _getRequiredBond(2) }(disputed, 2, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(3); + gameProxy.attack{ value: _getRequiredBond(3) }(disputed, 3, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(4); + gameProxy.attack{ value: _getRequiredBond(4) }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + (,,,, disputed,,) = gameProxy.claimData(5); + gameProxy.attack{ value: _getRequiredBond(5) }(disputed, 5, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(6); + gameProxy.attack{ value: _getRequiredBond(6) }(disputed, 6, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(7); + gameProxy.attack{ value: _getRequiredBond(7) }(disputed, 7, _dummyClaim()); + + // Verify game state before step + assertEq(uint256(gameProxy.status()), uint256(GameStatus.IN_PROGRESS)); + + gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); + gameProxy.step(8, true, absolutePrestateData, hex""); + + vm.warp(block.timestamp + gameProxy.maxClockDuration().raw() + 1); + gameProxy.resolveClaim(8, 0); + gameProxy.resolveClaim(7, 0); + gameProxy.resolveClaim(6, 0); + gameProxy.resolveClaim(5, 0); + gameProxy.resolveClaim(4, 0); + gameProxy.resolveClaim(3, 0); + gameProxy.resolveClaim(2, 0); + gameProxy.resolveClaim(1, 0); + + gameProxy.resolveClaim(0, 0); + gameProxy.resolve(); + + assertEq(uint256(gameProxy.status()), uint256(GameStatus.CHALLENGER_WINS)); + assertEq(gameProxy.resolvedAt().raw(), block.timestamp); + (, address counteredBy,,,,,) = gameProxy.claimData(0); + assertEq(counteredBy, CHALLENGER); + } + + /// @dev Helper to return a pseudo-random claim + function _dummyClaim() internal view returns (Claim) { + return Claim.wrap(keccak256(abi.encode(gasleft()))); + } + /// @dev Helper to get the required bond for the given claim index. function _getRequiredBond(uint256 _claimIndex) internal view returns (uint256 bond_) { (,,,,, Position parent,) = gameProxy.claimData(_claimIndex);