From 2b465ce4e32417db67c0f2a26b436124c9617614 Mon Sep 17 00:00:00 2001 From: inphi Date: Mon, 13 May 2024 12:57:42 -0400 Subject: [PATCH 1/8] dispute-game: Sanity check disputed claim index --- packages/contracts-bedrock/semver-lock.json | 4 +- .../src/dispute/FaultDisputeGame.sol | 17 +- .../src/dispute/PermissionedDisputeGame.sol | 17 +- .../dispute/interfaces/IFaultDisputeGame.sol | 12 +- .../src/dispute/lib/Errors.sol | 4 +- .../test/actors/FaultDisputeActors.sol | 3 +- .../test/dispute/FaultDisputeGame.t.sol | 357 ++++++++++++------ .../dispute/PermissionedDisputeGame.t.sol | 27 +- .../test/invariants/FaultDisputeGame.t.sol | 3 +- 9 files changed, 297 insertions(+), 147 deletions(-) diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index 12e084a83c4bf..2b8390b0faa6f 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -132,8 +132,8 @@ "sourceCodeHash": "0x918c395ac5d77357f2551616aad0613e68893862edd14e554623eb16ee6ba148" }, "src/dispute/FaultDisputeGame.sol": { - "initCodeHash": "0x923d5c668370010e84a0318a813c2979962b1007d692344f5496bcda6fa85e53", - "sourceCodeHash": "0xf77ee4322aeb08559469c3bd42ec266547a170b48ea1cffcf633de80543f3c09" + "initCodeHash": "0x5ea5b544b8d7b32f55f7864c25a2443a5db363ffd1c66e0799cbc7bccaf98526", + "sourceCodeHash": "0x1868f16d348eb0c7de17ffaaed758aeac946a2cb567af1c423a5db1dd71f9f3d" }, "src/dispute/weth/DelayedWETH.sol": { "initCodeHash": "0xb9bbe005874922cd8f499e7a0a092967cfca03e012c1e41912b0c77481c71777", diff --git a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol index 2698d97b23b89..a2ffb6690ab5b 100644 --- a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol @@ -69,8 +69,8 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { uint256 internal constant HEADER_BLOCK_NUMBER_INDEX = 8; /// @notice Semantic version. - /// @custom:semver 1.1.1 - string public constant version = "1.1.1"; + /// @custom:semver 1.2.0 + string public constant version = "1.2.0"; /// @notice The starting timestamp of the game Timestamp public createdAt; @@ -315,13 +315,16 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { /// @param _challengeIndex The index of the claim being moved against. /// @param _claim The claim at the next logical position in the game. /// @param _isAttack Whether or not the move is an attack or defense. - function move(uint256 _challengeIndex, Claim _claim, bool _isAttack) public payable virtual { + function move(Claim _disputed, uint256 _challengeIndex, Claim _claim, bool _isAttack) public payable virtual { // INVARIANT: Moves cannot be made unless the game is currently in progress. if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); // Get the parent. If it does not exist, the call will revert with OOB. ClaimData memory parent = claimData[_challengeIndex]; + // INVARIANT: The claim at the _challengeIndex must be the disputed claim. + if (Claim.unwrap(parent.claim) != Claim.unwrap(_disputed)) revert InvalidDisputedClaimIndex(); + // Compute the position that the claim commits to. Because the parent's position is already // known, we can compute the next position by moving left or right depending on whether // or not the move is an attack or defense. @@ -412,13 +415,13 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { } /// @inheritdoc IFaultDisputeGame - function attack(uint256 _parentIndex, Claim _claim) external payable { - move(_parentIndex, _claim, true); + function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable { + move(_disputed, _parentIndex, _claim, true); } /// @inheritdoc IFaultDisputeGame - function defend(uint256 _parentIndex, Claim _claim) external payable { - move(_parentIndex, _claim, false); + function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable { + move(_disputed, _parentIndex, _claim, false); } /// @inheritdoc IFaultDisputeGame diff --git a/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol b/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol index ba7c23ac6c02f..8e67415524898 100644 --- a/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol @@ -88,11 +88,22 @@ contract PermissionedDisputeGame is FaultDisputeGame { } /// @notice Generic move function, used for both `attack` and `defend` moves. - /// @param _challengeIndex The index of the claim being moved against. + /// @notice _disputed The disputed `Claim`. + /// @param _challengeIndex The index of the claim being moved against. This must match the `_disputed` claim. /// @param _claim The claim at the next logical position in the game. /// @param _isAttack Whether or not the move is an attack or defense. - function move(uint256 _challengeIndex, Claim _claim, bool _isAttack) public payable override onlyAuthorized { - super.move(_challengeIndex, _claim, _isAttack); + function move( + Claim _disputed, + uint256 _challengeIndex, + Claim _claim, + bool _isAttack + ) + public + payable + override + onlyAuthorized + { + super.move(_disputed, _challengeIndex, _claim, _isAttack); } /// @inheritdoc IInitializable diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol b/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol index 5d062faa80cf8..43de378ac06d1 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol @@ -34,14 +34,18 @@ interface IFaultDisputeGame is IDisputeGame { event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant); /// @notice Attack a disagreed upon `Claim`. - /// @param _parentIndex Index of the `Claim` to attack in the `claimData` array. + /// @param _disputed The `Claim` being attacked. + /// @param _parentIndex Index of the `Claim` to attack in the `claimData` array. This must match the `_disputed` + /// claim. /// @param _claim The `Claim` at the relative attack position. - function attack(uint256 _parentIndex, Claim _claim) external payable; + function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable; /// @notice Defend an agreed upon `Claim`. - /// @param _parentIndex Index of the claim to defend in the `claimData` array. + /// @notice _disputed The `Claim` being defended. + /// @param _parentIndex Index of the claim to defend in the `claimData` array. This must match the `_disputed` + /// claim. /// @param _claim The `Claim` at the relative defense position. - function defend(uint256 _parentIndex, Claim _claim) external payable; + function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable; /// @notice Perform an instruction step via an on-chain fault proof processor. /// @dev This function should point to a fault proof processor in order to execute diff --git a/packages/contracts-bedrock/src/dispute/lib/Errors.sol b/packages/contracts-bedrock/src/dispute/lib/Errors.sol index 8bc01f19f465d..9a3237b32d2c1 100644 --- a/packages/contracts-bedrock/src/dispute/lib/Errors.sol +++ b/packages/contracts-bedrock/src/dispute/lib/Errors.sol @@ -45,8 +45,8 @@ error CannotDefendRootClaim(); /// @notice Thrown when a claim is attempting to be made that already exists. error ClaimAlreadyExists(); -/// @notice Thrown when a given claim is invalid. -error InvalidClaim(); +/// @notice Thrown when a disputed claim does not match its index in the game. +error InvalidDisputedClaimIndex(); /// @notice Thrown when an action that requires the game to be `IN_PROGRESS` is invoked when /// the game is not in progress. diff --git a/packages/contracts-bedrock/test/actors/FaultDisputeActors.sol b/packages/contracts-bedrock/test/actors/FaultDisputeActors.sol index 9516d2fb4b03d..181fc87266acf 100644 --- a/packages/contracts-bedrock/test/actors/FaultDisputeActors.sol +++ b/packages/contracts-bedrock/test/actors/FaultDisputeActors.sol @@ -218,11 +218,12 @@ contract HonestGameSolver is GameSolver { bool isAttack = _direction == Direction.Attack; uint256 bond = GAME.getRequiredBond(_movePos); + (,,,, Claim disputed,,) = GAME.claimData(_challengeIndex); move_ = Move({ kind: isAttack ? MoveKind.Attack : MoveKind.Defend, value: bond, - data: abi.encodeCall(FaultDisputeGame.move, (_challengeIndex, claimAt(_movePos), isAttack)) + data: abi.encodeCall(FaultDisputeGame.move, (disputed, _challengeIndex, claimAt(_movePos), isAttack)) }); } diff --git a/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol index b0032ba2fd426..5954d65ba681b 100644 --- a/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol @@ -358,29 +358,32 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { GameStatus status = gameProxy.status(); assertEq(uint256(status), chalWins); + (,,,, Claim root,,) = gameProxy.claimData(0); // Attempt to make a move. Should revert. vm.expectRevert(GameNotInProgress.selector); - gameProxy.attack(0, Claim.wrap(0)); + gameProxy.attack(root, 0, Claim.wrap(0)); } /// @dev Tests that an attempt to defend the root claim reverts with the `CannotDefendRootClaim` error. function test_move_defendRoot_reverts() public { + (,,,, Claim root,,) = gameProxy.claimData(0); vm.expectRevert(CannotDefendRootClaim.selector); - gameProxy.defend(0, _dummyClaim()); + gameProxy.defend(root, 0, _dummyClaim()); } /// @dev Tests that an attempt to move against a claim that does not exist reverts with the /// `ParentDoesNotExist` error. function test_move_nonExistentParent_reverts() public { Claim claim = _dummyClaim(); + (,,,, Claim disputed,,) = gameProxy.claimData(1); // Expect an out of bounds revert for an attack vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x32)); - gameProxy.attack(1, claim); + gameProxy.attack(disputed, 1, claim); // Expect an out of bounds revert for a defense vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x32)); - gameProxy.defend(1, claim); + gameProxy.defend(disputed, 1, claim); } /// @dev Tests that an attempt to move at the maximum game depth reverts with the @@ -391,13 +394,14 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { uint256 maxDepth = gameProxy.maxGameDepth(); for (uint256 i = 0; i <= maxDepth; i++) { + (,,,, Claim disputed,,) = gameProxy.claimData(i); // At the max game depth, the `_move` function should revert with // the `GameDepthExceeded` error. if (i == maxDepth) { vm.expectRevert(GameDepthExceeded.selector); - gameProxy.attack{ value: 100 ether }(i, claim); + gameProxy.attack{ value: 100 ether }(disputed, i, claim); } else { - gameProxy.attack{ value: _getRequiredBond(i) }(i, claim); + gameProxy.attack{ value: _getRequiredBond(i) }(disputed, i, claim); } } } @@ -409,7 +413,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.warp(block.timestamp + 3 days + 12 hours + 1); uint256 bond = _getRequiredBond(0); vm.expectRevert(ClockTimeExceeded.selector); - gameProxy.attack{ value: bond }(0, _dummyClaim()); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: bond }(disputed, 0, _dummyClaim()); } /// @notice Static unit test for the correctness of the chess clock incrementation. @@ -421,13 +426,15 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.warp(block.timestamp + 15); uint256 bond = _getRequiredBond(0); - gameProxy.attack{ value: bond }(0, claim); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: bond }(disputed, 0, claim); (,,,,,, clock) = gameProxy.claimData(1); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(15), Timestamp.wrap(uint64(block.timestamp))).raw()); vm.warp(block.timestamp + 10); bond = _getRequiredBond(1); - gameProxy.attack{ value: bond }(1, claim); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.attack{ value: bond }(disputed, 1, claim); (,,,,,, clock) = gameProxy.claimData(2); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(10), Timestamp.wrap(uint64(block.timestamp))).raw()); @@ -437,13 +444,15 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.warp(block.timestamp + 10); bond = _getRequiredBond(2); - gameProxy.attack{ value: bond }(2, claim); + (,,,, disputed,,) = gameProxy.claimData(2); + gameProxy.attack{ value: bond }(disputed, 2, claim); (,,,,,, clock) = gameProxy.claimData(3); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(25), Timestamp.wrap(uint64(block.timestamp))).raw()); vm.warp(block.timestamp + 10); bond = _getRequiredBond(3); - gameProxy.attack{ value: bond }(3, claim); + (,,,, disputed,,) = gameProxy.claimData(3); + gameProxy.attack{ value: bond }(disputed, 3, claim); (,,,,,, clock) = gameProxy.claimData(4); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(20), Timestamp.wrap(uint64(block.timestamp))).raw()); } @@ -462,7 +471,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // allocated exactly `clockExtension` seconds remaining on their potential clock. vm.warp(block.timestamp + halfGameDuration - 1 seconds); uint256 bond = _getRequiredBond(0); - gameProxy.attack{ value: bond }(0, claim); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: bond }(disputed, 0, claim); (,,,,,, clock) = gameProxy.claimData(1); assertEq(clock.duration().raw(), halfGameDuration - clockExtension); @@ -471,7 +481,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.warp(block.timestamp + halfGameDuration - 1 seconds); for (uint256 i = 1; i < splitDepth - 2; i++) { bond = _getRequiredBond(i); - gameProxy.attack{ value: bond }(i, claim); + (,,,, disputed,,) = gameProxy.claimData(i); + gameProxy.attack{ value: bond }(disputed, i, claim); } // Warp ahead 1 seconds to have `clockExtension - 1 seconds` left on the next move's clock. @@ -481,7 +492,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // be allocated `clockExtension * 2` seconds on their potential clock, if currently they have less than // `clockExtension` seconds left. bond = _getRequiredBond(splitDepth - 2); - gameProxy.attack{ value: bond }(splitDepth - 2, claim); + (,,,, disputed,,) = gameProxy.claimData(splitDepth - 2); + gameProxy.attack{ value: bond }(disputed, splitDepth - 2, claim); (,,,,,, clock) = gameProxy.claimData(splitDepth - 1); assertEq(clock.duration().raw(), halfGameDuration - clockExtension * 2); } @@ -493,11 +505,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Make the first move. This should succeed. uint256 bond = _getRequiredBond(0); - gameProxy.attack{ value: bond }(0, claim); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: bond }(disputed, 0, claim); // Attempt to make the same move again. vm.expectRevert(ClaimAlreadyExists.selector); - gameProxy.attack{ value: bond }(0, claim); + gameProxy.attack{ value: bond }(disputed, 0, claim); } /// @dev Static unit test asserting that identical claims at the same position can be made in different subgames. @@ -507,15 +520,18 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Make the first moves. This should succeed. uint256 bond = _getRequiredBond(0); - gameProxy.attack{ value: bond }(0, claimA); - gameProxy.attack{ value: bond }(0, claimB); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: bond }(disputed, 0, claimA); + gameProxy.attack{ value: bond }(disputed, 0, claimB); // Perform an attack at the same position with the same claim value in both subgames. // These both should succeed. bond = _getRequiredBond(1); - gameProxy.attack{ value: bond }(1, claimA); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.attack{ value: bond }(disputed, 1, claimA); bond = _getRequiredBond(2); - gameProxy.attack{ value: bond }(2, claimA); + (,,,, disputed,,) = gameProxy.claimData(2); + gameProxy.attack{ value: bond }(disputed, 2, claimA); } /// @dev Static unit test for the correctness of an opening attack. @@ -529,7 +545,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { uint256 reqBond = _getRequiredBond(0); vm.expectEmit(true, true, true, false); emit Move(0, counter, address(this)); - gameProxy.attack{ value: reqBond }(0, counter); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: reqBond }(disputed, 0, counter); // Grab the claim data of the attack. ( @@ -567,30 +584,45 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Tests that making a claim at the execution trace bisection root level with an invalid status /// byte reverts with the `UnexpectedRootClaim` error. function test_move_incorrectStatusExecRoot_reverts() public { + Claim disputed; for (uint256 i; i < 4; i++) { - gameProxy.attack{ value: _getRequiredBond(i) }(i, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(i); + gameProxy.attack{ value: _getRequiredBond(i) }(disputed, i, _dummyClaim()); } uint256 bond = _getRequiredBond(4); vm.expectRevert(abi.encodeWithSelector(UnexpectedRootClaim.selector, bytes32(0))); - gameProxy.attack{ value: bond }(4, Claim.wrap(bytes32(0))); + (,,,, disputed,,) = gameProxy.claimData(4); + gameProxy.attack{ value: bond }(disputed, 4, Claim.wrap(bytes32(0))); } /// @dev Tests that making a claim at the execution trace bisection root level with a valid status /// byte succeeds. function test_move_correctStatusExecRoot_succeeds() public { + Claim disputed; for (uint256 i; i < 4; i++) { uint256 bond = _getRequiredBond(i); - gameProxy.attack{ value: bond }(i, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(i); + gameProxy.attack{ value: bond }(disputed, i, _dummyClaim()); } uint256 lastBond = _getRequiredBond(4); - gameProxy.attack{ value: lastBond }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + (,,,, disputed,,) = gameProxy.claimData(4); + gameProxy.attack{ value: lastBond }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); } /// @dev Static unit test asserting that a move reverts when the bonded amount is incorrect. function test_move_incorrectBondAmount_reverts() public { vm.expectRevert(IncorrectBondAmount.selector); - gameProxy.attack{ value: 0 }(0, _dummyClaim()); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: 0 }(disputed, 0, _dummyClaim()); + } + + /// @dev Static unit test asserting that a move reverts when the disputed claim does not match its index. + function test_move_incorrectDisputedIndex_reverts() public { + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: 0 }(disputed, 0, _dummyClaim()); + vm.expectRevert(InvalidDisputedClaimIndex.selector); + gameProxy.attack{ value: 0 }(disputed, 1, _dummyClaim()); } /// @dev Tests that challenging the root claim's L2 block number by providing the real preimage of the output root @@ -655,7 +687,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Attack the root as 0xb0b uint256 bond = _getRequiredBond(0); vm.prank(address(0xb0b)); - fdg.attack{ value: bond }(0, Claim.wrap(0)); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + fdg.attack{ value: bond }(disputed, 0, Claim.wrap(0)); // Challenge the L2 block number as 0xace. This claim should receive the root claim's bond. vm.prank(address(0xace)); @@ -761,14 +794,22 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.deal(address(this), 1000 ether); // Make claims all the way down the tree. - gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(2) }(2, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(3) }(3, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(4) }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); - gameProxy.attack{ value: _getRequiredBond(5) }(5, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(6) }(6, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(7) }(7, _dummyClaim()); + (,,,, 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()); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); gameProxy.step(8, true, absolutePrestateData, hex""); @@ -783,16 +824,24 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.deal(address(this), 1000 ether); // Make claims all the way down the tree. - gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(2) }(2, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(3) }(3, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(4) }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + (,,,, 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)); bytes memory claimData5 = abi.encode(5, 5); Claim claim5 = Claim.wrap(keccak256(claimData5)); - gameProxy.attack{ value: _getRequiredBond(5) }(5, claim5); - gameProxy.defend{ value: _getRequiredBond(6) }(6, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(7) }(7, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(5); + gameProxy.attack{ value: _getRequiredBond(5) }(disputed, 5, claim5); + (,,,, disputed,,) = gameProxy.claimData(6); + gameProxy.defend{ value: _getRequiredBond(6) }(disputed, 6, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(7); + gameProxy.attack{ value: _getRequiredBond(7) }(disputed, 7, _dummyClaim()); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); gameProxy.step(8, true, claimData5, hex""); } @@ -804,17 +853,25 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.deal(address(this), 1000 ether); // Make claims all the way down the tree. - gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(2) }(2, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(3) }(3, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(4) }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + (,,,, 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)); bytes memory claimData5 = abi.encode(5, 5); Claim claim5 = Claim.wrap(keccak256(claimData5)); - gameProxy.attack{ value: _getRequiredBond(5) }(5, claim5); - gameProxy.defend{ value: _getRequiredBond(6) }(6, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(5); + gameProxy.attack{ value: _getRequiredBond(5) }(disputed, 5, claim5); + (,,,, disputed,,) = gameProxy.claimData(6); + gameProxy.defend{ value: _getRequiredBond(6) }(disputed, 6, _dummyClaim()); Claim postState_ = Claim.wrap(gameImpl.vm().step(claimData5, hex"", bytes32(0))); - gameProxy.attack{ value: _getRequiredBond(7) }(7, postState_); + (,,,, disputed,,) = gameProxy.claimData(7); + gameProxy.attack{ value: _getRequiredBond(7) }(disputed, 7, postState_); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); vm.expectRevert(ValidStep.selector); @@ -828,21 +885,29 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.deal(address(this), 1000 ether); // Make claims all the way down the tree. - gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(2) }(2, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(3) }(3, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(4) }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + (,,,, 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)); bytes memory claimData7 = abi.encode(5, 5); Claim postState_ = Claim.wrap(gameImpl.vm().step(claimData7, hex"", bytes32(0))); - gameProxy.attack{ value: _getRequiredBond(5) }(5, postState_); - gameProxy.defend{ value: _getRequiredBond(6) }(6, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(5); + gameProxy.attack{ value: _getRequiredBond(5) }(disputed, 5, postState_); + (,,,, disputed,,) = gameProxy.claimData(6); + gameProxy.defend{ value: _getRequiredBond(6) }(disputed, 6, _dummyClaim()); bytes memory _dummyClaimData = abi.encode(gasleft(), gasleft()); Claim dummyClaim7 = Claim.wrap(keccak256(_dummyClaimData)); - gameProxy.attack{ value: _getRequiredBond(7) }(7, dummyClaim7); + (,,,, disputed,,) = gameProxy.claimData(7); + gameProxy.attack{ value: _getRequiredBond(7) }(disputed, 7, dummyClaim7); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); vm.expectRevert(ValidStep.selector); gameProxy.step(8, false, _dummyClaimData, hex""); @@ -855,19 +920,27 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.deal(address(this), 1000 ether); // Make claims all the way down the tree. - gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(2) }(2, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(3) }(3, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(4) }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + (,,,, 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)); bytes memory claimData7 = abi.encode(5, 5); Claim claim7 = Claim.wrap(keccak256(claimData7)); Claim postState_ = Claim.wrap(gameImpl.vm().step(claimData7, hex"", bytes32(0))); - gameProxy.attack{ value: _getRequiredBond(5) }(5, postState_); - gameProxy.defend{ value: _getRequiredBond(6) }(6, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(7) }(7, claim7); + (,,,, disputed,,) = gameProxy.claimData(5); + gameProxy.attack{ value: _getRequiredBond(5) }(disputed, 5, postState_); + (,,,, disputed,,) = gameProxy.claimData(6); + gameProxy.defend{ value: _getRequiredBond(6) }(disputed, 6, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(7); + gameProxy.attack{ value: _getRequiredBond(7) }(disputed, 7, claim7); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); vm.expectRevert(ValidStep.selector); @@ -894,7 +967,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { uint256 bond = _getRequiredBond(0); for (uint256 i = 0; i < 2048; i++) { - gameProxy.attack{ value: bond }(0, Claim.wrap(bytes32(i))); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: bond }(disputed, 0, Claim.wrap(bytes32(i))); } // Warp past the clock period. @@ -965,7 +1039,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Static unit test for the correctness of resolving a single attack game state. function test_resolve_rootContested_succeeds() public { - gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim()); vm.warp(block.timestamp + 3 days + 12 hours); @@ -976,8 +1051,10 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Static unit test for the correctness of resolving a game with a contested challenge claim. function test_resolve_challengeContested_succeeds() public { - gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); - gameProxy.defend{ value: _getRequiredBond(1) }(1, _dummyClaim()); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.defend{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim()); vm.warp(block.timestamp + 3 days + 12 hours); @@ -989,10 +1066,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Static unit test for the correctness of resolving a game with multiplayer moves. function test_resolve_teamDeathmatch_succeeds() public { - gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); - gameProxy.defend{ value: _getRequiredBond(1) }(1, _dummyClaim()); - gameProxy.defend{ value: _getRequiredBond(1) }(1, _dummyClaim()); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim()); + gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.defend{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim()); + gameProxy.defend{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim()); vm.warp(block.timestamp + 3 days + 12 hours); @@ -1008,12 +1087,14 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { function test_resolve_stepReached_succeeds() public { Claim claim = _dummyClaim(); for (uint256 i; i < gameProxy.splitDepth(); i++) { - gameProxy.attack{ value: _getRequiredBond(i) }(i, claim); + (,,,, Claim disputed,,) = gameProxy.claimData(i); + gameProxy.attack{ value: _getRequiredBond(i) }(disputed, i, claim); } claim = _changeClaimStatus(claim, VMStatuses.PANIC); for (uint256 i = gameProxy.claimDataLen() - 1; i < gameProxy.maxGameDepth(); i++) { - gameProxy.attack{ value: _getRequiredBond(i) }(i, claim); + (,,,, Claim disputed,,) = gameProxy.claimData(i); + gameProxy.attack{ value: _getRequiredBond(i) }(disputed, i, claim); } vm.warp(block.timestamp + 3 days + 12 hours); @@ -1029,10 +1110,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { Claim claim = _dummyClaim(); uint256 firstBond = _getRequiredBond(0); vm.deal(address(this), firstBond); - gameProxy.attack{ value: firstBond }(0, claim); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: firstBond }(disputed, 0, claim); uint256 secondBond = _getRequiredBond(1); vm.deal(address(this), secondBond); - gameProxy.attack{ value: secondBond }(1, claim); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.attack{ value: secondBond }(disputed, 1, claim); vm.warp(block.timestamp + 3 days + 12 hours); @@ -1055,13 +1138,15 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { function test_resolve_claimAtMaxDepthAlreadyResolved_reverts() public { Claim claim = _dummyClaim(); for (uint256 i; i < gameProxy.splitDepth(); i++) { - gameProxy.attack{ value: _getRequiredBond(i) }(i, claim); + (,,,, Claim disputed,,) = gameProxy.claimData(i); + gameProxy.attack{ value: _getRequiredBond(i) }(disputed, i, claim); } vm.deal(address(this), 10000 ether); claim = _changeClaimStatus(claim, VMStatuses.PANIC); for (uint256 i = gameProxy.claimDataLen() - 1; i < gameProxy.maxGameDepth(); i++) { - gameProxy.attack{ value: _getRequiredBond(i) }(i, claim); + (,,,, Claim disputed,,) = gameProxy.claimData(i); + gameProxy.attack{ value: _getRequiredBond(i) }(disputed, i, claim); } vm.warp(block.timestamp + 3 days + 12 hours); @@ -1082,8 +1167,10 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Static unit test asserting that resolve reverts when attempting to resolve subgames out of order function test_resolve_outOfOrderResolution_reverts() public { - gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); - gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); + (,,,, 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()); vm.warp(block.timestamp + 3 days + 12 hours); @@ -1101,28 +1188,36 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Make claims all the way down the tree. uint256 bond = _getRequiredBond(0); uint256 totalBonded = bond; - gameProxy.attack{ value: bond }(0, _dummyClaim()); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: bond }(disputed, 0, _dummyClaim()); bond = _getRequiredBond(1); totalBonded += bond; - gameProxy.attack{ value: bond }(1, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.attack{ value: bond }(disputed, 1, _dummyClaim()); bond = _getRequiredBond(2); totalBonded += bond; - gameProxy.attack{ value: bond }(2, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(2); + gameProxy.attack{ value: bond }(disputed, 2, _dummyClaim()); bond = _getRequiredBond(3); totalBonded += bond; - gameProxy.attack{ value: bond }(3, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(3); + gameProxy.attack{ value: bond }(disputed, 3, _dummyClaim()); bond = _getRequiredBond(4); totalBonded += bond; - gameProxy.attack{ value: bond }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + (,,,, disputed,,) = gameProxy.claimData(4); + gameProxy.attack{ value: bond }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); bond = _getRequiredBond(5); totalBonded += bond; - gameProxy.attack{ value: bond }(5, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(5); + gameProxy.attack{ value: bond }(disputed, 5, _dummyClaim()); bond = _getRequiredBond(6); totalBonded += bond; - gameProxy.attack{ value: bond }(6, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(6); + gameProxy.attack{ value: bond }(disputed, 6, _dummyClaim()); bond = _getRequiredBond(7); totalBonded += bond; - gameProxy.attack{ value: bond }(7, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(7); + gameProxy.attack{ value: bond }(disputed, 7, _dummyClaim()); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); gameProxy.step(8, true, absolutePrestateData, hex""); @@ -1169,39 +1264,47 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Make claims all the way down the tree, trading off between bob and the test contract. uint256 firstBond = _getRequiredBond(0); uint256 thisBonded = firstBond; - gameProxy.attack{ value: firstBond }(0, _dummyClaim()); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: firstBond }(disputed, 0, _dummyClaim()); uint256 secondBond = _getRequiredBond(1); uint256 bobBonded = secondBond; vm.prank(bob); - gameProxy.attack{ value: secondBond }(1, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.attack{ value: secondBond }(disputed, 1, _dummyClaim()); uint256 thirdBond = _getRequiredBond(2); thisBonded += thirdBond; - gameProxy.attack{ value: thirdBond }(2, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(2); + gameProxy.attack{ value: thirdBond }(disputed, 2, _dummyClaim()); uint256 fourthBond = _getRequiredBond(3); bobBonded += fourthBond; vm.prank(bob); - gameProxy.attack{ value: fourthBond }(3, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(3); + gameProxy.attack{ value: fourthBond }(disputed, 3, _dummyClaim()); uint256 fifthBond = _getRequiredBond(4); thisBonded += fifthBond; - gameProxy.attack{ value: fifthBond }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + (,,,, disputed,,) = gameProxy.claimData(4); + gameProxy.attack{ value: fifthBond }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); uint256 sixthBond = _getRequiredBond(5); bobBonded += sixthBond; vm.prank(bob); - gameProxy.attack{ value: sixthBond }(5, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(5); + gameProxy.attack{ value: sixthBond }(disputed, 5, _dummyClaim()); uint256 seventhBond = _getRequiredBond(6); thisBonded += seventhBond; - gameProxy.attack{ value: seventhBond }(6, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(6); + gameProxy.attack{ value: seventhBond }(disputed, 6, _dummyClaim()); uint256 eighthBond = _getRequiredBond(7); bobBonded += eighthBond; vm.prank(bob); - gameProxy.attack{ value: eighthBond }(7, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(7); + gameProxy.attack{ value: eighthBond }(disputed, 7, _dummyClaim()); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); gameProxy.step(8, true, absolutePrestateData, hex""); @@ -1260,18 +1363,21 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // alice is successfully countered by both bob and the test contract uint256 firstBond = _getRequiredBond(0); vm.prank(alice); - gameProxy.attack{ value: firstBond }(0, _dummyClaim()); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: firstBond }(disputed, 0, _dummyClaim()); uint256 secondBond = _getRequiredBond(1); vm.prank(bob); - gameProxy.defend{ value: secondBond }(1, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.defend{ value: secondBond }(disputed, 1, _dummyClaim()); vm.prank(charlie); - gameProxy.attack{ value: secondBond }(1, _dummyClaim()); - gameProxy.attack{ value: secondBond }(1, _dummyClaim()); + gameProxy.attack{ value: secondBond }(disputed, 1, _dummyClaim()); + gameProxy.attack{ value: secondBond }(disputed, 1, _dummyClaim()); uint256 thirdBond = _getRequiredBond(3); vm.prank(alice); - gameProxy.attack{ value: thirdBond }(3, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(3); + gameProxy.attack{ value: thirdBond }(disputed, 3, _dummyClaim()); // Resolve all claims vm.warp(block.timestamp + 3 days + 12 hours); @@ -1353,7 +1459,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { assert(l2BlockNumber < gameProxy.l2BlockNumber()); // Challenge the claim and resolve it. - gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim()); vm.warp(block.timestamp + 3 days + 12 hours); gameProxy.resolveClaim(1, 0); gameProxy.resolveClaim(0, 0); @@ -1377,10 +1484,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { Claim claim = _dummyClaim(); uint256 firstBond = _getRequiredBond(0); vm.deal(address(reenter), firstBond); - gameProxy.attack{ value: firstBond }(0, claim); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: firstBond }(disputed, 0, claim); uint256 secondBond = _getRequiredBond(1); vm.deal(address(reenter), secondBond); - gameProxy.attack{ value: secondBond }(1, claim); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.attack{ value: secondBond }(disputed, 1, claim); uint256 reenterBond = firstBond + secondBond; // Warp past the finalization period @@ -1422,13 +1531,16 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Tests that adding local data with an out of bounds identifier reverts. function testFuzz_addLocalData_oob_reverts(uint256 _ident) public { + Claim disputed; // Get a claim below the split depth so that we can add local data for an execution trace subgame. for (uint256 i; i < 4; i++) { uint256 bond = _getRequiredBond(i); - gameProxy.attack{ value: bond }(i, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(i); + gameProxy.attack{ value: bond }(disputed, i, _dummyClaim()); } uint256 lastBond = _getRequiredBond(4); - gameProxy.attack{ value: lastBond }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + (,,,, disputed,,) = gameProxy.claimData(4); + gameProxy.attack{ value: lastBond }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); // [1, 5] are valid local data identifiers. if (_ident <= 5) _ident = 0; @@ -1441,14 +1553,17 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// that is disputing the transition from `GENESIS -> GENESIS + 1` function test_addLocalDataGenesisTransition_static_succeeds() public { IPreimageOracle oracle = IPreimageOracle(address(gameProxy.vm().oracle())); + Claim disputed; // Get a claim below the split depth so that we can add local data for an execution trace subgame. for (uint256 i; i < 4; i++) { uint256 bond = _getRequiredBond(i); - gameProxy.attack{ value: bond }(i, Claim.wrap(bytes32(i))); + (,,,, disputed,,) = gameProxy.claimData(i); + gameProxy.attack{ value: bond }(disputed, i, Claim.wrap(bytes32(i))); } uint256 lastBond = _getRequiredBond(4); - gameProxy.attack{ value: lastBond }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + (,,,, disputed,,) = gameProxy.claimData(4); + gameProxy.attack{ value: lastBond }(disputed, 4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); // Expected start/disputed claims (Hash root,) = gameProxy.startingOutputRoot(); @@ -1489,14 +1604,17 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Tests that local data is loaded into the preimage oracle correctly. function test_addLocalDataMiddle_static_succeeds() public { IPreimageOracle oracle = IPreimageOracle(address(gameProxy.vm().oracle())); + Claim disputed; // Get a claim below the split depth so that we can add local data for an execution trace subgame. for (uint256 i; i < 4; i++) { uint256 bond = _getRequiredBond(i); - gameProxy.attack{ value: bond }(i, Claim.wrap(bytes32(i))); + (,,,, disputed,,) = gameProxy.claimData(i); + gameProxy.attack{ value: bond }(disputed, i, Claim.wrap(bytes32(i))); } uint256 lastBond = _getRequiredBond(4); - gameProxy.defend{ value: lastBond }(4, _changeClaimStatus(ROOT_CLAIM, VMStatuses.VALID)); + (,,,, disputed,,) = gameProxy.claimData(4); + gameProxy.defend{ value: lastBond }(disputed, 4, _changeClaimStatus(ROOT_CLAIM, VMStatuses.VALID)); // Expected start/disputed claims bytes32 startingClaim = bytes32(uint256(3)); @@ -1541,7 +1659,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Defender's turn vm.warp(block.timestamp + 3.5 days - 1 seconds); - gameProxy.attack{ value: _getRequiredBond(0) }(0, _dummyClaim()); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim()); // Chess clock time accumulated: assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days - 1 seconds); assertEq(gameProxy.getChallengerDuration(1).raw(), 0); @@ -1551,7 +1670,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Attempt a second attack against the root claim. This should revert since the challenger clock is expired. uint256 expectedBond = _getRequiredBond(0); vm.expectRevert(ClockTimeExceeded.selector); - gameProxy.attack{ value: expectedBond }(0, _dummyClaim()); + gameProxy.attack{ value: expectedBond }(disputed, 0, _dummyClaim()); // Chess clock time accumulated: assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days); assertEq(gameProxy.getChallengerDuration(1).raw(), 1 seconds); @@ -1565,7 +1684,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Warp to the last second of the root claim defender clock. vm.warp(block.timestamp + 3.5 days - 2 seconds); // Attack the challenge to the root claim. This should succeed, since the defender clock is not expired. - gameProxy.attack{ value: _getRequiredBond(1) }(1, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.attack{ value: _getRequiredBond(1) }(disputed, 1, _dummyClaim()); // Chess clock time accumulated: assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days); assertEq(gameProxy.getChallengerDuration(1).raw(), 3.5 days - 1 seconds); @@ -1598,10 +1718,11 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.warp(block.timestamp + 1 seconds); expectedBond = _getRequiredBond(1); vm.expectRevert(ClockTimeExceeded.selector); // no further move can be made - gameProxy.attack{ value: expectedBond }(1, _dummyClaim()); + gameProxy.attack{ value: expectedBond }(disputed, 1, _dummyClaim()); expectedBond = _getRequiredBond(2); vm.expectRevert(ClockTimeExceeded.selector); // no further move can be made - gameProxy.attack{ value: expectedBond }(2, _dummyClaim()); + (,,,, disputed,,) = gameProxy.claimData(2); + gameProxy.attack{ value: expectedBond }(disputed, 2, _dummyClaim()); // Chess clock time accumulated: assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days); assertEq(gameProxy.getChallengerDuration(1).raw(), 3.5 days); diff --git a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol index 1247ec5bd8376..5069fa65ccbaf 100644 --- a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol @@ -131,13 +131,16 @@ contract PermissionedDisputeGame_Test is PermissionedDisputeGame_Init { vm.startPrank(CHALLENGER, CHALLENGER); uint256 firstBond = _getRequiredBond(0); vm.deal(CHALLENGER, firstBond); - gameProxy.attack{ value: firstBond }(0, Claim.wrap(0)); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: firstBond }(disputed, 0, Claim.wrap(0)); uint256 secondBond = _getRequiredBond(1); vm.deal(CHALLENGER, secondBond); - gameProxy.defend{ value: secondBond }(1, Claim.wrap(0)); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.defend{ value: secondBond }(disputed, 1, Claim.wrap(0)); uint256 thirdBond = _getRequiredBond(2); vm.deal(CHALLENGER, thirdBond); - gameProxy.move{ value: thirdBond }(2, Claim.wrap(0), true); + (,,,, disputed,,) = gameProxy.claimData(2); + gameProxy.move{ value: thirdBond }(disputed, 2, Claim.wrap(0), true); vm.stopPrank(); } @@ -146,13 +149,16 @@ contract PermissionedDisputeGame_Test is PermissionedDisputeGame_Init { vm.startPrank(PROPOSER, PROPOSER); uint256 firstBond = _getRequiredBond(0); vm.deal(PROPOSER, firstBond); - gameProxy.attack{ value: firstBond }(0, Claim.wrap(0)); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack{ value: firstBond }(disputed, 0, Claim.wrap(0)); uint256 secondBond = _getRequiredBond(1); vm.deal(PROPOSER, secondBond); - gameProxy.defend{ value: secondBond }(1, Claim.wrap(0)); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.defend{ value: secondBond }(disputed, 1, Claim.wrap(0)); uint256 thirdBond = _getRequiredBond(2); vm.deal(PROPOSER, thirdBond); - gameProxy.move{ value: thirdBond }(2, Claim.wrap(0), true); + (,,,, disputed,,) = gameProxy.claimData(2); + gameProxy.move{ value: thirdBond }(disputed, 2, Claim.wrap(0), true); vm.stopPrank(); } @@ -163,11 +169,14 @@ contract PermissionedDisputeGame_Test is PermissionedDisputeGame_Init { vm.startPrank(_p, _p); vm.expectRevert(BadAuth.selector); - gameProxy.attack(0, Claim.wrap(0)); + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attack(disputed, 0, Claim.wrap(0)); vm.expectRevert(BadAuth.selector); - gameProxy.defend(1, Claim.wrap(0)); + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.defend(disputed, 1, Claim.wrap(0)); vm.expectRevert(BadAuth.selector); - gameProxy.move(2, Claim.wrap(0), true); + (,,,, disputed,,) = gameProxy.claimData(2); + gameProxy.move(disputed, 2, Claim.wrap(0), true); vm.expectRevert(BadAuth.selector); gameProxy.step(0, true, absolutePrestateData, hex""); vm.stopPrank(); diff --git a/packages/contracts-bedrock/test/invariants/FaultDisputeGame.t.sol b/packages/contracts-bedrock/test/invariants/FaultDisputeGame.t.sol index 2eb8727595714..295b9f315abf8 100644 --- a/packages/contracts-bedrock/test/invariants/FaultDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/invariants/FaultDisputeGame.t.sol @@ -89,7 +89,8 @@ contract RandomClaimActor is StdUtils { totalBonded += _bondAmount; - GAME.move{ value: _bondAmount }(_parentIndex, _claim, _isAttack); + (,,,, Claim disputed,,) = GAME.claimData(_parentIndex); + GAME.move{ value: _bondAmount }(disputed, _parentIndex, _claim, _isAttack); } fallback() external payable { } From cd829289fda0967259c8a18f2c08faf769291bd9 Mon Sep 17 00:00:00 2001 From: inphi Date: Mon, 13 May 2024 15:00:13 -0400 Subject: [PATCH 2/8] Fix tests --- .../test/dispute/FaultDisputeGame.t.sol | 49 ++++++++++--------- .../dispute/PermissionedDisputeGame.t.sol | 8 ++- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol index 5954d65ba681b..81e24d08b0eb4 100644 --- a/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol @@ -375,15 +375,14 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// `ParentDoesNotExist` error. function test_move_nonExistentParent_reverts() public { Claim claim = _dummyClaim(); - (,,,, Claim disputed,,) = gameProxy.claimData(1); // Expect an out of bounds revert for an attack vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x32)); - gameProxy.attack(disputed, 1, claim); + gameProxy.attack(_dummyClaim(), 1, claim); // Expect an out of bounds revert for a defense vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x32)); - gameProxy.defend(disputed, 1, claim); + gameProxy.defend(_dummyClaim(), 1, claim); } /// @dev Tests that an attempt to move at the maximum game depth reverts with the @@ -412,8 +411,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Warp ahead past the clock time for the first move (3 1/2 days) vm.warp(block.timestamp + 3 days + 12 hours + 1); uint256 bond = _getRequiredBond(0); - vm.expectRevert(ClockTimeExceeded.selector); (,,,, Claim disputed,,) = gameProxy.claimData(0); + vm.expectRevert(ClockTimeExceeded.selector); gameProxy.attack{ value: bond }(disputed, 0, _dummyClaim()); } @@ -591,8 +590,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { } uint256 bond = _getRequiredBond(4); - vm.expectRevert(abi.encodeWithSelector(UnexpectedRootClaim.selector, bytes32(0))); (,,,, disputed,,) = gameProxy.claimData(4); + vm.expectRevert(abi.encodeWithSelector(UnexpectedRootClaim.selector, bytes32(0))); gameProxy.attack{ value: bond }(disputed, 4, Claim.wrap(bytes32(0))); } @@ -612,17 +611,18 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Static unit test asserting that a move reverts when the bonded amount is incorrect. function test_move_incorrectBondAmount_reverts() public { - vm.expectRevert(IncorrectBondAmount.selector); (,,,, Claim disputed,,) = gameProxy.claimData(0); + vm.expectRevert(IncorrectBondAmount.selector); gameProxy.attack{ value: 0 }(disputed, 0, _dummyClaim()); } /// @dev Static unit test asserting that a move reverts when the disputed claim does not match its index. function test_move_incorrectDisputedIndex_reverts() public { (,,,, Claim disputed,,) = gameProxy.claimData(0); - gameProxy.attack{ value: 0 }(disputed, 0, _dummyClaim()); + gameProxy.attack{ value: _getRequiredBond(0) }(disputed, 0, _dummyClaim()); + uint256 bond = _getRequiredBond(1); vm.expectRevert(InvalidDisputedClaimIndex.selector); - gameProxy.attack{ value: 0 }(disputed, 1, _dummyClaim()); + gameProxy.attack{ value: bond }(disputed, 1, _dummyClaim()); } /// @dev Tests that challenging the root claim's L2 block number by providing the real preimage of the output root @@ -686,8 +686,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Attack the root as 0xb0b uint256 bond = _getRequiredBond(0); + (,,,, Claim disputed,,) = fdg.claimData(0); vm.prank(address(0xb0b)); - (,,,, Claim disputed,,) = gameProxy.claimData(0); fdg.attack{ value: bond }(disputed, 0, Claim.wrap(0)); // Challenge the L2 block number as 0xace. This claim should receive the root claim's bond. @@ -1256,10 +1256,11 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// moves with 2 actors and a dishonest root claim. function test_resolve_bondPayoutsSeveralActors_succeeds() public { // Give the test contract and bob some ether - uint256 bal = 1000 ether; + // We use the "1000 ether" literal for `bal`, the initial balance, to avoid stack too deep + //uint256 bal = 1000 ether; address bob = address(0xb0b); - vm.deal(address(this), bal); - vm.deal(bob, bal); + vm.deal(address(this), 1000 ether); + vm.deal(bob, 1000 ether); // Make claims all the way down the tree, trading off between bob and the test contract. uint256 firstBond = _getRequiredBond(0); @@ -1269,8 +1270,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { uint256 secondBond = _getRequiredBond(1); uint256 bobBonded = secondBond; - vm.prank(bob); (,,,, disputed,,) = gameProxy.claimData(1); + vm.prank(bob); gameProxy.attack{ value: secondBond }(disputed, 1, _dummyClaim()); uint256 thirdBond = _getRequiredBond(2); @@ -1280,8 +1281,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { uint256 fourthBond = _getRequiredBond(3); bobBonded += fourthBond; - vm.prank(bob); (,,,, disputed,,) = gameProxy.claimData(3); + vm.prank(bob); gameProxy.attack{ value: fourthBond }(disputed, 3, _dummyClaim()); uint256 fifthBond = _getRequiredBond(4); @@ -1291,8 +1292,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { uint256 sixthBond = _getRequiredBond(5); bobBonded += sixthBond; - vm.prank(bob); (,,,, disputed,,) = gameProxy.claimData(5); + vm.prank(bob); gameProxy.attack{ value: sixthBond }(disputed, 5, _dummyClaim()); uint256 seventhBond = _getRequiredBond(6); @@ -1302,8 +1303,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { uint256 eighthBond = _getRequiredBond(7); bobBonded += eighthBond; - vm.prank(bob); (,,,, disputed,,) = gameProxy.claimData(7); + vm.prank(bob); gameProxy.attack{ value: eighthBond }(disputed, 7, _dummyClaim()); gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); @@ -1314,8 +1315,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { assertEq(counteredBy, address(this)); // Ensure we bonded the correct amounts - assertEq(address(this).balance, bal - thisBonded); - assertEq(bob.balance, bal - bobBonded); + assertEq(address(this).balance, 1000 ether - thisBonded); + assertEq(bob.balance, 1000 ether - bobBonded); assertEq(address(gameProxy).balance, 0); assertEq(delayedWeth.balanceOf(address(gameProxy)), thisBonded + bobBonded); @@ -1337,8 +1338,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { gameProxy.claimCredit(bob); // Ensure that bonds were paid out correctly. - assertEq(address(this).balance, bal + bobBonded); - assertEq(bob.balance, bal - bobBonded); + assertEq(address(this).balance, 1000 ether + bobBonded); + assertEq(bob.balance, 1000 ether - bobBonded); assertEq(address(gameProxy).balance, 0); assertEq(delayedWeth.balanceOf(address(gameProxy)), 0); @@ -1362,21 +1363,21 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // charlie is successfully countered by alice // alice is successfully countered by both bob and the test contract uint256 firstBond = _getRequiredBond(0); - vm.prank(alice); (,,,, Claim disputed,,) = gameProxy.claimData(0); + vm.prank(alice); gameProxy.attack{ value: firstBond }(disputed, 0, _dummyClaim()); uint256 secondBond = _getRequiredBond(1); - vm.prank(bob); (,,,, disputed,,) = gameProxy.claimData(1); + vm.prank(bob); gameProxy.defend{ value: secondBond }(disputed, 1, _dummyClaim()); vm.prank(charlie); gameProxy.attack{ value: secondBond }(disputed, 1, _dummyClaim()); gameProxy.attack{ value: secondBond }(disputed, 1, _dummyClaim()); uint256 thirdBond = _getRequiredBond(3); - vm.prank(alice); (,,,, disputed,,) = gameProxy.claimData(3); + vm.prank(alice); gameProxy.attack{ value: thirdBond }(disputed, 3, _dummyClaim()); // Resolve all claims @@ -1720,8 +1721,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.expectRevert(ClockTimeExceeded.selector); // no further move can be made gameProxy.attack{ value: expectedBond }(disputed, 1, _dummyClaim()); expectedBond = _getRequiredBond(2); - vm.expectRevert(ClockTimeExceeded.selector); // no further move can be made (,,,, disputed,,) = gameProxy.claimData(2); + vm.expectRevert(ClockTimeExceeded.selector); // no further move can be made gameProxy.attack{ value: expectedBond }(disputed, 2, _dummyClaim()); // Chess clock time accumulated: assertEq(gameProxy.getChallengerDuration(0).raw(), 3.5 days); diff --git a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol index 5069fa65ccbaf..5d3fc6f70f799 100644 --- a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol @@ -168,15 +168,13 @@ contract PermissionedDisputeGame_Test is PermissionedDisputeGame_Init { vm.assume(_p != PROPOSER && _p != CHALLENGER); vm.startPrank(_p, _p); - vm.expectRevert(BadAuth.selector); (,,,, Claim disputed,,) = gameProxy.claimData(0); + vm.expectRevert(BadAuth.selector); gameProxy.attack(disputed, 0, Claim.wrap(0)); vm.expectRevert(BadAuth.selector); - (,,,, disputed,,) = gameProxy.claimData(1); - gameProxy.defend(disputed, 1, Claim.wrap(0)); + gameProxy.defend(disputed, 0, Claim.wrap(0)); vm.expectRevert(BadAuth.selector); - (,,,, disputed,,) = gameProxy.claimData(2); - gameProxy.move(disputed, 2, Claim.wrap(0), true); + gameProxy.move(disputed, 0, Claim.wrap(0), true); vm.expectRevert(BadAuth.selector); gameProxy.step(0, true, absolutePrestateData, hex""); vm.stopPrank(); From 459130482f73b31cde98e56dc8320a3d72032c18 Mon Sep 17 00:00:00 2001 From: inphi Date: Mon, 13 May 2024 15:45:35 -0400 Subject: [PATCH 3/8] update snapshots --- .../snapshots/abi/FaultDisputeGame.json | 20 +++++++++++++++++++ .../abi/PermissionedDisputeGame.json | 20 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/packages/contracts-bedrock/snapshots/abi/FaultDisputeGame.json b/packages/contracts-bedrock/snapshots/abi/FaultDisputeGame.json index f0558ad5961b4..e9527c8a4f44d 100644 --- a/packages/contracts-bedrock/snapshots/abi/FaultDisputeGame.json +++ b/packages/contracts-bedrock/snapshots/abi/FaultDisputeGame.json @@ -106,6 +106,11 @@ }, { "inputs": [ + { + "internalType": "Claim", + "name": "_disputed", + "type": "bytes32" + }, { "internalType": "uint256", "name": "_parentIndex", @@ -303,6 +308,11 @@ }, { "inputs": [ + { + "internalType": "Claim", + "name": "_disputed", + "type": "bytes32" + }, { "internalType": "uint256", "name": "_parentIndex", @@ -538,6 +548,11 @@ }, { "inputs": [ + { + "internalType": "Claim", + "name": "_disputed", + "type": "bytes32" + }, { "internalType": "uint256", "name": "_challengeIndex", @@ -958,6 +973,11 @@ "name": "InvalidDataRemainder", "type": "error" }, + { + "inputs": [], + "name": "InvalidDisputedClaimIndex", + "type": "error" + }, { "inputs": [], "name": "InvalidHeader", diff --git a/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json b/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json index b0093118232c8..f9849492b8d0c 100644 --- a/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json +++ b/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json @@ -116,6 +116,11 @@ }, { "inputs": [ + { + "internalType": "Claim", + "name": "_disputed", + "type": "bytes32" + }, { "internalType": "uint256", "name": "_parentIndex", @@ -326,6 +331,11 @@ }, { "inputs": [ + { + "internalType": "Claim", + "name": "_disputed", + "type": "bytes32" + }, { "internalType": "uint256", "name": "_parentIndex", @@ -561,6 +571,11 @@ }, { "inputs": [ + { + "internalType": "Claim", + "name": "_disputed", + "type": "bytes32" + }, { "internalType": "uint256", "name": "_challengeIndex", @@ -999,6 +1014,11 @@ "name": "InvalidDataRemainder", "type": "error" }, + { + "inputs": [], + "name": "InvalidDisputedClaimIndex", + "type": "error" + }, { "inputs": [], "name": "InvalidHeader", From b9f1ffcc6397846bd314b07f1e7fe50ee3e00128 Mon Sep 17 00:00:00 2001 From: inphi Date: Mon, 13 May 2024 19:00:54 -0400 Subject: [PATCH 4/8] fix docs --- packages/contracts-bedrock/semver-lock.json | 2 +- packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index 2b8390b0faa6f..11c3c9dc4e240 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -133,7 +133,7 @@ }, "src/dispute/FaultDisputeGame.sol": { "initCodeHash": "0x5ea5b544b8d7b32f55f7864c25a2443a5db363ffd1c66e0799cbc7bccaf98526", - "sourceCodeHash": "0x1868f16d348eb0c7de17ffaaed758aeac946a2cb567af1c423a5db1dd71f9f3d" + "sourceCodeHash": "0x827cc088deb92345d7e4dc53157203cd4e0f05d15ff4fdc8707fdc959c1415a8" }, "src/dispute/weth/DelayedWETH.sol": { "initCodeHash": "0xb9bbe005874922cd8f499e7a0a092967cfca03e012c1e41912b0c77481c71777", diff --git a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol index a2ffb6690ab5b..4eda56268016a 100644 --- a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol @@ -312,6 +312,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { } /// @notice Generic move function, used for both `attack` and `defend` moves. + /// @notice _disputed The disputed `Claim`. /// @param _challengeIndex The index of the claim being moved against. /// @param _claim The claim at the next logical position in the game. /// @param _isAttack Whether or not the move is an attack or defense. From 8b4b7c115bc2ccd072cdc0b90ad10fceaa4ea09a Mon Sep 17 00:00:00 2001 From: inphi Date: Mon, 13 May 2024 19:36:25 -0400 Subject: [PATCH 5/8] move param --- packages/contracts-bedrock/semver-lock.json | 2 +- packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index 11c3c9dc4e240..4325677bc9761 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -133,7 +133,7 @@ }, "src/dispute/FaultDisputeGame.sol": { "initCodeHash": "0x5ea5b544b8d7b32f55f7864c25a2443a5db363ffd1c66e0799cbc7bccaf98526", - "sourceCodeHash": "0x827cc088deb92345d7e4dc53157203cd4e0f05d15ff4fdc8707fdc959c1415a8" + "sourceCodeHash": "0xe8d90f1a8f92732707e370767df260bc806be5be9808f150ebed2c6caa158734" }, "src/dispute/weth/DelayedWETH.sol": { "initCodeHash": "0xb9bbe005874922cd8f499e7a0a092967cfca03e012c1e41912b0c77481c71777", diff --git a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol index 4eda56268016a..ab559147ed175 100644 --- a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol @@ -312,7 +312,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { } /// @notice Generic move function, used for both `attack` and `defend` moves. - /// @notice _disputed The disputed `Claim`. + /// @param _disputed The disputed `Claim`. /// @param _challengeIndex The index of the claim being moved against. /// @param _claim The claim at the next logical position in the game. /// @param _isAttack Whether or not the move is an attack or defense. From 741b362b18b227a01bdc8b2d6eb05897856e66b0 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 14 May 2024 08:59:01 +1000 Subject: [PATCH 6/8] op-challenger: Supply parent value when performing moves Also moves calculation of the required bond into the contract bindings so the returned TxCandidate is ready to send. --- op-challenger/cmd/move.go | 8 +- op-challenger/game/fault/agent.go | 4 +- .../game/fault/contracts/faultdisputegame.go | 28 +++-- .../fault/contracts/faultdisputegame0180.go | 12 ++ .../fault/contracts/faultdisputegame080.go | 10 ++ .../fault/contracts/faultdisputegame_test.go | 31 ++++- .../game/fault/responder/responder.go | 23 +--- .../game/fault/responder/responder_test.go | 110 +++++++++--------- .../game/fault/solver/game_solver.go | 22 ++-- .../game/fault/solver/game_solver_test.go | 14 +-- op-challenger/game/fault/solver/rules.go | 38 +++--- op-challenger/game/fault/test/game_builder.go | 44 ++++--- op-challenger/game/fault/types/actions.go | 5 +- 13 files changed, 193 insertions(+), 156 deletions(-) diff --git a/op-challenger/cmd/move.go b/op-challenger/cmd/move.go index 5e24d065b23c5..e7cf2587aa4fc 100644 --- a/op-challenger/cmd/move.go +++ b/op-challenger/cmd/move.go @@ -51,14 +51,18 @@ func Move(ctx *cli.Context) error { return fmt.Errorf("failed to create dispute game bindings: %w", err) } + parentClaim, err := contract.GetClaim(ctx.Context, parentIndex) + if err != nil { + return fmt.Errorf("failed to get parent claim: %w", err) + } var tx txmgr.TxCandidate if attack { - tx, err = contract.AttackTx(parentIndex, claim) + tx, err = contract.AttackTx(ctx.Context, parentClaim, claim) if err != nil { return fmt.Errorf("failed to create attack tx: %w", err) } } else if defend { - tx, err = contract.DefendTx(parentIndex, claim) + tx, err = contract.DefendTx(ctx.Context, parentClaim, claim) if err != nil { return fmt.Errorf("failed to create defense tx: %w", err) } diff --git a/op-challenger/game/fault/agent.go b/op-challenger/game/fault/agent.go index 54a4c92fe4895..46951d23e7768 100644 --- a/op-challenger/game/fault/agent.go +++ b/op-challenger/game/fault/agent.go @@ -120,7 +120,7 @@ func (a *Agent) performAction(ctx context.Context, wg *sync.WaitGroup, action ty isLocal := containsOracleData && action.OracleData.IsLocal actionLog = actionLog.New( "is_attack", action.IsAttack, - "parent", action.ParentIdx, + "parent", action.ParentClaim.ContractIndex, "prestate", common.Bytes2Hex(action.PreState), "proof", common.Bytes2Hex(action.ProofData), "containsOracleData", containsOracleData, @@ -130,7 +130,7 @@ func (a *Agent) performAction(ctx context.Context, wg *sync.WaitGroup, action ty actionLog = actionLog.New("oracleKey", common.Bytes2Hex(action.OracleData.OracleKey)) } } else if action.Type == types.ActionTypeMove { - actionLog = actionLog.New("is_attack", action.IsAttack, "parent", action.ParentIdx, "value", action.Value) + actionLog = actionLog.New("is_attack", action.IsAttack, "parent", action.ParentClaim.ContractIndex, "value", action.Value) } switch action.Type { diff --git a/op-challenger/game/fault/contracts/faultdisputegame.go b/op-challenger/game/fault/contracts/faultdisputegame.go index bbef7c162b8ad..64c93d19d4da3 100644 --- a/op-challenger/game/fault/contracts/faultdisputegame.go +++ b/op-challenger/game/fault/contracts/faultdisputegame.go @@ -480,14 +480,26 @@ func (f *FaultDisputeGameContractLatest) ChallengeL2BlockNumberTx(challenge *typ }, headerRlp).ToTxCandidate() } -func (f *FaultDisputeGameContractLatest) AttackTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) { - call := f.contract.Call(methodAttack, new(big.Int).SetUint64(parentContractIndex), pivot) - return call.ToTxCandidate() +func (f *FaultDisputeGameContractLatest) AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) { + call := f.contract.Call(methodAttack, parent.Value, big.NewInt(int64(parent.ContractIndex)), pivot) + return f.txWithBond(ctx, parent.Position.Attack(), call) } -func (f *FaultDisputeGameContractLatest) DefendTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) { - call := f.contract.Call(methodDefend, new(big.Int).SetUint64(parentContractIndex), pivot) - return call.ToTxCandidate() +func (f *FaultDisputeGameContractLatest) DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) { + call := f.contract.Call(methodDefend, parent.Value, big.NewInt(int64(parent.ContractIndex)), pivot) + return f.txWithBond(ctx, parent.Position.Defend(), call) +} + +func (f *FaultDisputeGameContractLatest) txWithBond(ctx context.Context, position types.Position, call *batching.ContractCall) (txmgr.TxCandidate, error) { + tx, err := call.ToTxCandidate() + if err != nil { + return txmgr.TxCandidate{}, fmt.Errorf("failed to create transaction: %w", err) + } + tx.Value, err = f.GetRequiredBond(ctx, position) + if err != nil { + return txmgr.TxCandidate{}, fmt.Errorf("failed to fetch required bond: %w", err) + } + return tx, nil } func (f *FaultDisputeGameContractLatest) StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error) { @@ -595,8 +607,8 @@ type FaultDisputeGameContract interface { IsResolved(ctx context.Context, block rpcblock.Block, claims ...types.Claim) ([]bool, error) IsL2BlockNumberChallenged(ctx context.Context, block rpcblock.Block) (bool, error) ChallengeL2BlockNumberTx(challenge *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error) - AttackTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) - DefendTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) + AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) + DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error) CallResolveClaim(ctx context.Context, claimIdx uint64) error ResolveClaimTx(claimIdx uint64) (txmgr.TxCandidate, error) diff --git a/op-challenger/game/fault/contracts/faultdisputegame0180.go b/op-challenger/game/fault/contracts/faultdisputegame0180.go index a421ed06a4d75..3fad2aec75a4e 100644 --- a/op-challenger/game/fault/contracts/faultdisputegame0180.go +++ b/op-challenger/game/fault/contracts/faultdisputegame0180.go @@ -4,11 +4,13 @@ import ( "context" _ "embed" "fmt" + "math/big" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" ) //go:embed abis/FaultDisputeGame-0.18.1.json @@ -59,3 +61,13 @@ func (f *FaultDisputeGameContract0180) IsL2BlockNumberChallenged(_ context.Conte func (f *FaultDisputeGameContract0180) ChallengeL2BlockNumberTx(_ *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error) { return txmgr.TxCandidate{}, ErrChallengeL2BlockNotSupported } + +func (f *FaultDisputeGameContract0180) AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) { + call := f.contract.Call(methodAttack, big.NewInt(int64(parent.ContractIndex)), pivot) + return f.txWithBond(ctx, parent.Position.Attack(), call) +} + +func (f *FaultDisputeGameContract0180) DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) { + call := f.contract.Call(methodDefend, big.NewInt(int64(parent.ContractIndex)), pivot) + return f.txWithBond(ctx, parent.Position.Defend(), call) +} diff --git a/op-challenger/game/fault/contracts/faultdisputegame080.go b/op-challenger/game/fault/contracts/faultdisputegame080.go index 8ed76c4df3c22..cc30d21d7f941 100644 --- a/op-challenger/game/fault/contracts/faultdisputegame080.go +++ b/op-challenger/game/fault/contracts/faultdisputegame080.go @@ -146,3 +146,13 @@ func (f *FaultDisputeGameContract080) IsL2BlockNumberChallenged(_ context.Contex func (f *FaultDisputeGameContract080) ChallengeL2BlockNumberTx(_ *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error) { return txmgr.TxCandidate{}, ErrChallengeL2BlockNotSupported } + +func (f *FaultDisputeGameContract080) AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) { + call := f.contract.Call(methodAttack, big.NewInt(int64(parent.ContractIndex)), pivot) + return f.txWithBond(ctx, parent.Position.Attack(), call) +} + +func (f *FaultDisputeGameContract080) DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) { + call := f.contract.Call(methodDefend, big.NewInt(int64(parent.ContractIndex)), pivot) + return f.txWithBond(ctx, parent.Position.Defend(), call) +} diff --git a/op-challenger/game/fault/contracts/faultdisputegame_test.go b/op-challenger/game/fault/contracts/faultdisputegame_test.go index 6b0cfdad9c5df..65e49cb6e1637 100644 --- a/op-challenger/game/fault/contracts/faultdisputegame_test.go +++ b/op-challenger/game/fault/contracts/faultdisputegame_test.go @@ -7,6 +7,7 @@ import ( "math" "math/big" "math/rand" + "slices" "testing" "time" @@ -37,10 +38,14 @@ type contractVersion struct { loadAbi func() *abi.ABI } +func (c contractVersion) Is(versions ...string) bool { + return slices.Contains(versions, c.version) +} + const ( vers080 = "0.8.0" vers0180 = "0.18.0" - versLatest = "1.1.0" + versLatest = "1.2.0" ) var versions = []contractVersion{ @@ -379,11 +384,19 @@ func TestAttackTx(t *testing.T) { version := version t.Run(version.version, func(t *testing.T) { stubRpc, game := setupFaultDisputeGameTest(t, version) + bond := big.NewInt(1044) value := common.Hash{0xaa} - stubRpc.SetResponse(fdgAddr, methodAttack, rpcblock.Latest, []interface{}{big.NewInt(111), value}, nil) - tx, err := game.AttackTx(111, value) + parent := faultTypes.Claim{ClaimData: faultTypes.ClaimData{Value: common.Hash{0xbb}}, ContractIndex: 111} + stubRpc.SetResponse(fdgAddr, methodRequiredBond, rpcblock.Latest, []interface{}{parent.Position.Attack().ToGIndex()}, []interface{}{bond}) + if version.Is(vers080, vers0180) { + stubRpc.SetResponse(fdgAddr, methodAttack, rpcblock.Latest, []interface{}{big.NewInt(111), value}, nil) + } else { + stubRpc.SetResponse(fdgAddr, methodAttack, rpcblock.Latest, []interface{}{parent.Value, big.NewInt(111), value}, nil) + } + tx, err := game.AttackTx(context.Background(), parent, value) require.NoError(t, err) stubRpc.VerifyTxCandidate(tx) + require.Equal(t, bond, tx.Value) }) } } @@ -393,11 +406,19 @@ func TestDefendTx(t *testing.T) { version := version t.Run(version.version, func(t *testing.T) { stubRpc, game := setupFaultDisputeGameTest(t, version) + bond := big.NewInt(1044) value := common.Hash{0xaa} - stubRpc.SetResponse(fdgAddr, methodDefend, rpcblock.Latest, []interface{}{big.NewInt(111), value}, nil) - tx, err := game.DefendTx(111, value) + parent := faultTypes.Claim{ClaimData: faultTypes.ClaimData{Value: common.Hash{0xbb}}, ContractIndex: 111} + stubRpc.SetResponse(fdgAddr, methodRequiredBond, rpcblock.Latest, []interface{}{parent.Position.Defend().ToGIndex()}, []interface{}{bond}) + if version.Is(vers080, vers0180) { + stubRpc.SetResponse(fdgAddr, methodDefend, rpcblock.Latest, []interface{}{big.NewInt(111), value}, nil) + } else { + stubRpc.SetResponse(fdgAddr, methodDefend, rpcblock.Latest, []interface{}{parent.Value, big.NewInt(111), value}, nil) + } + tx, err := game.DefendTx(context.Background(), parent, value) require.NoError(t, err) stubRpc.VerifyTxCandidate(tx) + require.Equal(t, bond, tx.Value) }) } } diff --git a/op-challenger/game/fault/responder/responder.go b/op-challenger/game/fault/responder/responder.go index 9acbff1b6c1cd..8d0b257c5d6f6 100644 --- a/op-challenger/game/fault/responder/responder.go +++ b/op-challenger/game/fault/responder/responder.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "math/big" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/preimages" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" @@ -19,11 +18,10 @@ type GameContract interface { ResolveTx() (txmgr.TxCandidate, error) CallResolveClaim(ctx context.Context, claimIdx uint64) error ResolveClaimTx(claimIdx uint64) (txmgr.TxCandidate, error) - AttackTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) - DefendTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) + AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) + DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error) ChallengeL2BlockNumberTx(challenge *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error) - GetRequiredBond(ctx context.Context, position types.Position) (*big.Int, error) } type Oracle interface { @@ -101,7 +99,7 @@ func (r *FaultResponder) PerformAction(ctx context.Context, action types.Action) } // Always upload local preimages if !preimageExists { - err := r.uploader.UploadPreimage(ctx, uint64(action.ParentIdx), action.OracleData) + err := r.uploader.UploadPreimage(ctx, uint64(action.ParentClaim.ContractIndex), action.OracleData) if errors.Is(err, preimages.ErrChallengePeriodNotOver) { r.log.Debug("Large Preimage Squeeze failed, challenge period not over") return nil @@ -114,22 +112,13 @@ func (r *FaultResponder) PerformAction(ctx context.Context, action types.Action) var err error switch action.Type { case types.ActionTypeMove: - var movePos types.Position if action.IsAttack { - movePos = action.ParentPosition.Attack() - candidate, err = r.contract.AttackTx(uint64(action.ParentIdx), action.Value) + candidate, err = r.contract.AttackTx(ctx, action.ParentClaim, action.Value) } else { - movePos = action.ParentPosition.Defend() - candidate, err = r.contract.DefendTx(uint64(action.ParentIdx), action.Value) + candidate, err = r.contract.DefendTx(ctx, action.ParentClaim, action.Value) } - - bondValue, err := r.contract.GetRequiredBond(ctx, movePos) - if err != nil { - return err - } - candidate.Value = bondValue case types.ActionTypeStep: - candidate, err = r.contract.StepTx(uint64(action.ParentIdx), action.IsAttack, action.PreState, action.ProofData) + candidate, err = r.contract.StepTx(uint64(action.ParentClaim.ContractIndex), action.IsAttack, action.PreState, action.ProofData) case types.ActionTypeChallengeL2BlockNumber: candidate, err = r.contract.ChallengeL2BlockNumberTx(action.InvalidL2BlockNumberChallenge) } diff --git a/op-challenger/game/fault/responder/responder_test.go b/op-challenger/game/fault/responder/responder_test.go index 76d743c6e4a3b..35ed1e55916ff 100644 --- a/op-challenger/game/fault/responder/responder_test.go +++ b/op-challenger/game/fault/responder/responder_test.go @@ -109,10 +109,10 @@ func TestPerformAction(t *testing.T) { responder, mockTxMgr, _, _, _ := newTestFaultResponder(t) mockTxMgr.sendFails = true err := responder.PerformAction(context.Background(), types.Action{ - Type: types.ActionTypeMove, - ParentIdx: 123, - IsAttack: true, - Value: common.Hash{0xaa}, + Type: types.ActionTypeMove, + ParentClaim: types.Claim{ContractIndex: 123}, + IsAttack: true, + Value: common.Hash{0xaa}, }) require.ErrorIs(t, err, mockSendError) require.Equal(t, 0, mockTxMgr.sends) @@ -121,10 +121,10 @@ func TestPerformAction(t *testing.T) { t.Run("sends response", func(t *testing.T) { responder, mockTxMgr, _, _, _ := newTestFaultResponder(t) err := responder.PerformAction(context.Background(), types.Action{ - Type: types.ActionTypeMove, - ParentIdx: 123, - IsAttack: true, - Value: common.Hash{0xaa}, + Type: types.ActionTypeMove, + ParentClaim: types.Claim{ContractIndex: 123}, + IsAttack: true, + Value: common.Hash{0xaa}, }) require.NoError(t, err) require.Equal(t, 1, mockTxMgr.sends) @@ -133,60 +133,60 @@ func TestPerformAction(t *testing.T) { t.Run("attack", func(t *testing.T) { responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t) action := types.Action{ - Type: types.ActionTypeMove, - ParentIdx: 123, - IsAttack: true, - Value: common.Hash{0xaa}, + Type: types.ActionTypeMove, + ParentClaim: types.Claim{ContractIndex: 123}, + IsAttack: true, + Value: common.Hash{0xaa}, } err := responder.PerformAction(context.Background(), action) require.NoError(t, err) require.Len(t, mockTxMgr.sent, 1) - require.EqualValues(t, []interface{}{uint64(action.ParentIdx), action.Value}, contract.attackArgs) + require.EqualValues(t, []interface{}{action.ParentClaim, action.Value}, contract.attackArgs) require.Equal(t, ([]byte)("attack"), mockTxMgr.sent[0].TxData) }) t.Run("defend", func(t *testing.T) { responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t) action := types.Action{ - Type: types.ActionTypeMove, - ParentIdx: 123, - IsAttack: false, - Value: common.Hash{0xaa}, + Type: types.ActionTypeMove, + ParentClaim: types.Claim{ContractIndex: 123}, + IsAttack: false, + Value: common.Hash{0xaa}, } err := responder.PerformAction(context.Background(), action) require.NoError(t, err) require.Len(t, mockTxMgr.sent, 1) - require.EqualValues(t, []interface{}{uint64(action.ParentIdx), action.Value}, contract.defendArgs) + require.EqualValues(t, []interface{}{action.ParentClaim, action.Value}, contract.defendArgs) require.Equal(t, ([]byte)("defend"), mockTxMgr.sent[0].TxData) }) t.Run("step", func(t *testing.T) { responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t) action := types.Action{ - Type: types.ActionTypeStep, - ParentIdx: 123, - IsAttack: true, - PreState: []byte{1, 2, 3}, - ProofData: []byte{4, 5, 6}, + Type: types.ActionTypeStep, + ParentClaim: types.Claim{ContractIndex: 123}, + IsAttack: true, + PreState: []byte{1, 2, 3}, + ProofData: []byte{4, 5, 6}, } err := responder.PerformAction(context.Background(), action) require.NoError(t, err) require.Len(t, mockTxMgr.sent, 1) - require.EqualValues(t, []interface{}{uint64(action.ParentIdx), action.IsAttack, action.PreState, action.ProofData}, contract.stepArgs) + require.EqualValues(t, []interface{}{uint64(123), action.IsAttack, action.PreState, action.ProofData}, contract.stepArgs) require.Equal(t, ([]byte)("step"), mockTxMgr.sent[0].TxData) }) t.Run("stepWithLocalOracleData", func(t *testing.T) { responder, mockTxMgr, contract, uploader, oracle := newTestFaultResponder(t) action := types.Action{ - Type: types.ActionTypeStep, - ParentIdx: 123, - IsAttack: true, - PreState: []byte{1, 2, 3}, - ProofData: []byte{4, 5, 6}, + Type: types.ActionTypeStep, + ParentClaim: types.Claim{ContractIndex: 123}, + IsAttack: true, + PreState: []byte{1, 2, 3}, + ProofData: []byte{4, 5, 6}, OracleData: &types.PreimageOracleData{ IsLocal: true, }, @@ -204,11 +204,11 @@ func TestPerformAction(t *testing.T) { t.Run("stepWithGlobalOracleData", func(t *testing.T) { responder, mockTxMgr, contract, uploader, oracle := newTestFaultResponder(t) action := types.Action{ - Type: types.ActionTypeStep, - ParentIdx: 123, - IsAttack: true, - PreState: []byte{1, 2, 3}, - ProofData: []byte{4, 5, 6}, + Type: types.ActionTypeStep, + ParentClaim: types.Claim{ContractIndex: 123}, + IsAttack: true, + PreState: []byte{1, 2, 3}, + ProofData: []byte{4, 5, 6}, OracleData: &types.PreimageOracleData{ IsLocal: false, }, @@ -227,11 +227,11 @@ func TestPerformAction(t *testing.T) { responder, mockTxMgr, contract, uploader, _ := newTestFaultResponder(t) uploader.uploadFails = true action := types.Action{ - Type: types.ActionTypeStep, - ParentIdx: 123, - IsAttack: true, - PreState: []byte{1, 2, 3}, - ProofData: []byte{4, 5, 6}, + Type: types.ActionTypeStep, + ParentClaim: types.Claim{ContractIndex: 123}, + IsAttack: true, + PreState: []byte{1, 2, 3}, + ProofData: []byte{4, 5, 6}, OracleData: &types.PreimageOracleData{ IsLocal: true, }, @@ -247,11 +247,11 @@ func TestPerformAction(t *testing.T) { responder, mockTxMgr, contract, uploader, oracle := newTestFaultResponder(t) oracle.existsResult = true action := types.Action{ - Type: types.ActionTypeStep, - ParentIdx: 123, - IsAttack: true, - PreState: []byte{1, 2, 3}, - ProofData: []byte{4, 5, 6}, + Type: types.ActionTypeStep, + ParentClaim: types.Claim{ContractIndex: 123}, + IsAttack: true, + PreState: []byte{1, 2, 3}, + ProofData: []byte{4, 5, 6}, OracleData: &types.PreimageOracleData{ IsLocal: false, }, @@ -268,11 +268,11 @@ func TestPerformAction(t *testing.T) { responder, mockTxMgr, contract, uploader, oracle := newTestFaultResponder(t) oracle.existsFails = true action := types.Action{ - Type: types.ActionTypeStep, - ParentIdx: 123, - IsAttack: true, - PreState: []byte{1, 2, 3}, - ProofData: []byte{4, 5, 6}, + Type: types.ActionTypeStep, + ParentClaim: types.Claim{ContractIndex: 123}, + IsAttack: true, + PreState: []byte{1, 2, 3}, + ProofData: []byte{4, 5, 6}, OracleData: &types.PreimageOracleData{ IsLocal: false, }, @@ -406,13 +406,13 @@ func (m *mockContract) ChallengeL2BlockNumberTx(challenge *types.InvalidL2BlockN return txmgr.TxCandidate{TxData: ([]byte)("challenge")}, nil } -func (m *mockContract) AttackTx(parentClaimId uint64, claim common.Hash) (txmgr.TxCandidate, error) { - m.attackArgs = []interface{}{parentClaimId, claim} +func (m *mockContract) AttackTx(_ context.Context, parent types.Claim, claim common.Hash) (txmgr.TxCandidate, error) { + m.attackArgs = []interface{}{parent, claim} return txmgr.TxCandidate{TxData: ([]byte)("attack")}, nil } -func (m *mockContract) DefendTx(parentClaimId uint64, claim common.Hash) (txmgr.TxCandidate, error) { - m.defendArgs = []interface{}{parentClaimId, claim} +func (m *mockContract) DefendTx(_ context.Context, parent types.Claim, claim common.Hash) (txmgr.TxCandidate, error) { + m.defendArgs = []interface{}{parent, claim} return txmgr.TxCandidate{TxData: ([]byte)("defend")}, nil } @@ -427,10 +427,6 @@ func (m *mockContract) UpdateOracleTx(_ context.Context, claimIdx uint64, data * return txmgr.TxCandidate{TxData: ([]byte)("updateOracle")}, nil } -func (m *mockContract) GetRequiredBond(_ context.Context, position types.Position) (*big.Int, error) { - return big.NewInt(5), nil -} - func (m *mockContract) GetCredit(_ context.Context, _ common.Address) (*big.Int, error) { return big.NewInt(5), nil } diff --git a/op-challenger/game/fault/solver/game_solver.go b/op-challenger/game/fault/solver/game_solver.go index 812936cc4f840..9ba77c895b17a 100644 --- a/op-challenger/game/fault/solver/game_solver.go +++ b/op-challenger/game/fault/solver/game_solver.go @@ -85,13 +85,12 @@ func (s *GameSolver) calculateStep(ctx context.Context, game types.Game, claim t return nil, nil } return &types.Action{ - Type: types.ActionTypeStep, - ParentIdx: step.LeafClaim.ContractIndex, - ParentPosition: step.LeafClaim.Position, - IsAttack: step.IsAttack, - PreState: step.PreState, - ProofData: step.ProofData, - OracleData: step.OracleData, + Type: types.ActionTypeStep, + ParentClaim: step.LeafClaim, + IsAttack: step.IsAttack, + PreState: step.PreState, + ProofData: step.ProofData, + OracleData: step.OracleData, }, nil } @@ -108,10 +107,9 @@ func (s *GameSolver) calculateMove(ctx context.Context, game types.Game, claim t return nil, nil } return &types.Action{ - Type: types.ActionTypeMove, - IsAttack: !game.DefendsParent(*move), - ParentIdx: move.ParentContractIndex, - ParentPosition: claim.Position, - Value: move.Value, + Type: types.ActionTypeMove, + IsAttack: !game.DefendsParent(*move), + ParentClaim: game.Claims()[move.ParentContractIndex], + Value: move.Value, }, nil } diff --git a/op-challenger/game/fault/solver/game_solver_test.go b/op-challenger/game/fault/solver/game_solver_test.go index b0586a335ab2f..cde0420eda863 100644 --- a/op-challenger/game/fault/solver/game_solver_test.go +++ b/op-challenger/game/fault/solver/game_solver_test.go @@ -209,7 +209,7 @@ func TestCalculateNextActions(t *testing.T) { postState, actions := runStep(t, solver, game, claimBuilder.CorrectTraceProvider()) for i, action := range builder.ExpectedActions { t.Logf("Expect %v: Type: %v, ParentIdx: %v, Attack: %v, Value: %v, PreState: %v, ProofData: %v", - i, action.Type, action.ParentIdx, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData)) + i, action.Type, action.ParentClaim.ContractIndex, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData)) require.Containsf(t, actions, action, "Expected claim %v missing", i) } require.Len(t, actions, len(builder.ExpectedActions), "Incorrect number of actions") @@ -227,7 +227,7 @@ func runStep(t *testing.T, solver *GameSolver, game types.Game, correctTraceProv for i, action := range actions { t.Logf("Move %v: Type: %v, ParentIdx: %v, Attack: %v, Value: %v, PreState: %v, ProofData: %v", - i, action.Type, action.ParentIdx, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData)) + i, action.Type, action.ParentClaim.ContractIndex, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData)) // Check that every move the solver returns meets the generic validation rules require.NoError(t, checkRules(game, action, correctTraceProvider), "Attempting to perform invalid action") } @@ -333,9 +333,9 @@ func applyActions(game types.Game, claimant common.Address, actions []types.Acti for _, action := range actions { switch action.Type { case types.ActionTypeMove: - newPosition := action.ParentPosition.Attack() + newPosition := action.ParentClaim.Position.Attack() if !action.IsAttack { - newPosition = action.ParentPosition.Defend() + newPosition = action.ParentClaim.Position.Defend() } claim := types.Claim{ ClaimData: types.ClaimData{ @@ -345,13 +345,13 @@ func applyActions(game types.Game, claimant common.Address, actions []types.Acti }, Claimant: claimant, ContractIndex: len(claims), - ParentContractIndex: action.ParentIdx, + ParentContractIndex: action.ParentClaim.ContractIndex, } claims = append(claims, claim) case types.ActionTypeStep: - counteredClaim := claims[action.ParentIdx] + counteredClaim := claims[action.ParentClaim.ContractIndex] counteredClaim.CounteredBy = claimant - claims[action.ParentIdx] = counteredClaim + claims[action.ParentClaim.ContractIndex] = counteredClaim default: panic(fmt.Errorf("unknown move type: %v", action.Type)) } diff --git a/op-challenger/game/fault/solver/rules.go b/op-challenger/game/fault/solver/rules.go index 5a77ca5869a51..5a6dba60b29c2 100644 --- a/op-challenger/game/fault/solver/rules.go +++ b/op-challenger/game/fault/solver/rules.go @@ -46,8 +46,8 @@ func checkRules(game types.Game, action types.Action, correctTrace types.TracePr // parentMustExist checks that every action performed has a valid parent claim // Rationale: The action would be rejected by the contracts func parentMustExist(game types.Game, action types.Action, _ types.TraceProvider) error { - if len(game.Claims()) <= action.ParentIdx || action.ParentIdx < 0 { - return fmt.Errorf("parent claim %v does not exist in game with %v claims", action.ParentIdx, len(game.Claims())) + if len(game.Claims()) <= action.ParentClaim.ContractIndex || action.ParentClaim.ContractIndex < 0 { + return fmt.Errorf("parent claim %v does not exist in game with %v claims", action.ParentClaim.ContractIndex, len(game.Claims())) } return nil } @@ -58,7 +58,7 @@ func onlyStepAtMaxDepth(game types.Game, action types.Action, _ types.TraceProvi if action.Type == types.ActionTypeStep { return nil } - parentDepth := game.Claims()[action.ParentIdx].Position.Depth() + parentDepth := game.Claims()[action.ParentClaim.ContractIndex].Position.Depth() if parentDepth >= game.MaxDepth() { return fmt.Errorf("parent at max depth (%v) but attempting to perform %v action instead of step", parentDepth, action.Type) @@ -72,7 +72,7 @@ func onlyMoveBeforeMaxDepth(game types.Game, action types.Action, _ types.TraceP if action.Type == types.ActionTypeMove { return nil } - parentDepth := game.Claims()[action.ParentIdx].Position.Depth() + parentDepth := game.Claims()[action.ParentClaim.ContractIndex].Position.Depth() if parentDepth < game.MaxDepth() { return fmt.Errorf("parent (%v) not at max depth (%v) but attempting to perform %v action instead of move", parentDepth, game.MaxDepth(), action.Type) @@ -87,7 +87,7 @@ func doNotDuplicateExistingMoves(game types.Game, action types.Action, _ types.T Value: action.Value, Position: resultingPosition(game, action), } - if game.IsDuplicate(types.Claim{ClaimData: newClaimData, ParentContractIndex: action.ParentIdx}) { + if game.IsDuplicate(types.Claim{ClaimData: newClaimData, ParentContractIndex: action.ParentClaim.ContractIndex}) { return fmt.Errorf("creating duplicate claim at %v with value %v", newClaimData.Position.ToGIndex(), newClaimData.Value) } return nil @@ -96,7 +96,7 @@ func doNotDuplicateExistingMoves(game types.Game, action types.Action, _ types.T // doNotStepAlreadyCounteredClaims checks the challenger does not attempt to call step on already countered claims // Rationale: The step call is redundant and a waste of gas func doNotStepAlreadyCounteredClaims(game types.Game, action types.Action, _ types.TraceProvider) error { - claim := game.Claims()[action.ParentIdx] + claim := game.Claims()[action.ParentClaim.ContractIndex] if claim.CounteredBy != (common.Address{}) { return fmt.Errorf("attempting to step already countered claim: %v", claim.ContractIndex) } @@ -106,8 +106,8 @@ func doNotStepAlreadyCounteredClaims(game types.Game, action types.Action, _ typ // doNotDefendRootClaim checks the challenger doesn't attempt to defend the root claim // Rationale: The action would be rejected by the contracts func doNotDefendRootClaim(game types.Game, action types.Action, _ types.TraceProvider) error { - if game.Claims()[action.ParentIdx].IsRootPosition() && !action.IsAttack { - return fmt.Errorf("defending the root claim at idx %v", action.ParentIdx) + if game.Claims()[action.ParentClaim.ContractIndex].IsRootPosition() && !action.IsAttack { + return fmt.Errorf("defending the root claim at idx %v", action.ParentClaim.ContractIndex) } return nil } @@ -115,9 +115,9 @@ func doNotDefendRootClaim(game types.Game, action types.Action, _ types.TracePro // doNotCounterSelf checks the challenger doesn't counter its own claims // Rationale: The challenger should not disagree with itself func doNotCounterSelf(game types.Game, action types.Action, _ types.TraceProvider) error { - claim := game.Claims()[action.ParentIdx] + claim := game.Claims()[action.ParentClaim.ContractIndex] if claim.Claimant == challengerAddr { - return fmt.Errorf("countering own claim at idx %v", action.ParentIdx) + return fmt.Errorf("countering own claim at idx %v", action.ParentClaim.ContractIndex) } return nil } @@ -136,7 +136,7 @@ func avoidPoisonedPrestate(game types.Game, action types.Action, correctTrace ty movePosition := resultingPosition(game, action) honestTraceIndex := movePosition.TraceIndex(game.MaxDepth()) // Walk back up the claims and find the claim with highest trace index < honestTraceIndex - claim := game.Claims()[action.ParentIdx] + claim := game.Claims()[action.ParentClaim.ContractIndex] var preStateClaim types.Claim for { ancestors += printClaim(claim, game) + "\n" @@ -164,7 +164,7 @@ func avoidPoisonedPrestate(game types.Game, action types.Action, correctTrace ty return fmt.Errorf("failed to get correct trace at position %v: %w", preStateClaim.Position, err) } if correctValue != preStateClaim.Value { - err = fmt.Errorf("prestate poisoned claim %v has invalid prestate and is left of honest claim countering %v at trace index %v", preStateClaim.ContractIndex, action.ParentIdx, honestTraceIndex) + err = fmt.Errorf("prestate poisoned claim %v has invalid prestate and is left of honest claim countering %v at trace index %v", preStateClaim.ContractIndex, action.ParentClaim.ContractIndex, honestTraceIndex) return err } return nil @@ -199,10 +199,10 @@ func detectFailedStep(game types.Game, action types.Action, correctTrace types.T poststateIndex = new(big.Int).Add(honestTraceIndex, big.NewInt(1)) } // Walk back up the claims and find the claim required post state index - claim := game.Claims()[action.ParentIdx] + claim := game.Claims()[action.ParentClaim.ContractIndex] poststateClaim, ok := game.AncestorWithTraceIndex(claim, poststateIndex) if !ok { - return fmt.Errorf("did not find required poststate at %v to counter claim %v", poststateIndex, action.ParentIdx) + return fmt.Errorf("did not find required poststate at %v to counter claim %v", poststateIndex, action.ParentClaim.ContractIndex) } correctValue, err := correctTrace.Get(context.Background(), poststateClaim.Position) if err != nil { @@ -212,7 +212,7 @@ func detectFailedStep(game types.Game, action types.Action, correctTrace types.T parentPostAgree := (claim.Depth()-poststateClaim.Depth())%2 == 0 if parentPostAgree == validStep { return fmt.Errorf("failed step against claim at %v using poststate from claim %v post state is correct? %v parentPostAgree? %v", - action.ParentIdx, poststateClaim.ContractIndex, validStep, parentPostAgree) + action.ParentClaim.ContractIndex, poststateClaim.ContractIndex, validStep, parentPostAgree) } return nil } @@ -242,7 +242,7 @@ func detectPoisonedStepPrestate(game types.Game, action types.Action, correctTra return nil } // Walk back up the claims and find the claim with highest trace index < honestTraceIndex - claim := game.Claims()[action.ParentIdx] + claim := game.Claims()[action.ParentClaim.ContractIndex] preStateClaim, ok := game.AncestorWithTraceIndex(claim, prestateIndex) if !ok { return fmt.Errorf("performing step against claim %v with no prestate available at %v", claim.ContractIndex, prestateIndex) @@ -253,9 +253,9 @@ func detectPoisonedStepPrestate(game types.Game, action types.Action, correctTra } if correctValue != preStateClaim.Value { if action.Type == types.ActionTypeStep { - return fmt.Errorf("stepping from poisoned prestate at claim %v when countering %v", preStateClaim.ContractIndex, action.ParentIdx) + return fmt.Errorf("stepping from poisoned prestate at claim %v when countering %v", preStateClaim.ContractIndex, action.ParentClaim.ContractIndex) } else { - return fmt.Errorf("posting leaf claim with poisoned prestate from claim %v when countering %v", preStateClaim.ContractIndex, action.ParentIdx) + return fmt.Errorf("posting leaf claim with poisoned prestate from claim %v when countering %v", preStateClaim.ContractIndex, action.ParentClaim.ContractIndex) } } if action.Type == types.ActionTypeStep { @@ -268,7 +268,7 @@ func detectPoisonedStepPrestate(game types.Game, action types.Action, correctTra } func resultingPosition(game types.Game, action types.Action) types.Position { - parentPos := game.Claims()[action.ParentIdx].Position + parentPos := game.Claims()[action.ParentClaim.ContractIndex].Position if action.Type == types.ActionTypeStep { return parentPos } diff --git a/op-challenger/game/fault/test/game_builder.go b/op-challenger/game/fault/test/game_builder.go index 331d59c60be07..d55d650c2e2c5 100644 --- a/op-challenger/game/fault/test/game_builder.go +++ b/op-challenger/game/fault/test/game_builder.go @@ -102,11 +102,10 @@ func (s *GameBuilderSeq) ExpectAttack() *GameBuilderSeq { newPos := s.lastClaim.Position.Attack() value := s.builder.CorrectClaimAtPosition(newPos) s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{ - Type: types.ActionTypeMove, - ParentIdx: s.lastClaim.ContractIndex, - ParentPosition: s.lastClaim.Position, - IsAttack: true, - Value: value, + Type: types.ActionTypeMove, + ParentClaim: s.lastClaim, + IsAttack: true, + Value: value, }) return s } @@ -115,11 +114,10 @@ func (s *GameBuilderSeq) ExpectDefend() *GameBuilderSeq { newPos := s.lastClaim.Position.Defend() value := s.builder.CorrectClaimAtPosition(newPos) s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{ - Type: types.ActionTypeMove, - ParentIdx: s.lastClaim.ContractIndex, - ParentPosition: s.lastClaim.Position, - IsAttack: false, - Value: value, + Type: types.ActionTypeMove, + ParentClaim: s.lastClaim, + IsAttack: false, + Value: value, }) return s } @@ -127,13 +125,12 @@ func (s *GameBuilderSeq) ExpectDefend() *GameBuilderSeq { func (s *GameBuilderSeq) ExpectStepAttack() *GameBuilderSeq { traceIdx := s.lastClaim.TraceIndex(s.builder.maxDepth) s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{ - Type: types.ActionTypeStep, - ParentIdx: s.lastClaim.ContractIndex, - ParentPosition: s.lastClaim.Position, - IsAttack: true, - PreState: s.builder.CorrectPreState(traceIdx), - ProofData: s.builder.CorrectProofData(traceIdx), - OracleData: s.builder.CorrectOracleData(traceIdx), + Type: types.ActionTypeStep, + ParentClaim: s.lastClaim, + IsAttack: true, + PreState: s.builder.CorrectPreState(traceIdx), + ProofData: s.builder.CorrectProofData(traceIdx), + OracleData: s.builder.CorrectOracleData(traceIdx), }) return s } @@ -141,13 +138,12 @@ func (s *GameBuilderSeq) ExpectStepAttack() *GameBuilderSeq { func (s *GameBuilderSeq) ExpectStepDefend() *GameBuilderSeq { traceIdx := new(big.Int).Add(s.lastClaim.TraceIndex(s.builder.maxDepth), big.NewInt(1)) s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{ - Type: types.ActionTypeStep, - ParentIdx: s.lastClaim.ContractIndex, - ParentPosition: s.lastClaim.Position, - IsAttack: false, - PreState: s.builder.CorrectPreState(traceIdx), - ProofData: s.builder.CorrectProofData(traceIdx), - OracleData: s.builder.CorrectOracleData(traceIdx), + Type: types.ActionTypeStep, + ParentClaim: s.lastClaim, + IsAttack: false, + PreState: s.builder.CorrectPreState(traceIdx), + ProofData: s.builder.CorrectProofData(traceIdx), + OracleData: s.builder.CorrectOracleData(traceIdx), }) return s } diff --git a/op-challenger/game/fault/types/actions.go b/op-challenger/game/fault/types/actions.go index a0d3588e50df4..e5093d6ac553d 100644 --- a/op-challenger/game/fault/types/actions.go +++ b/op-challenger/game/fault/types/actions.go @@ -18,9 +18,8 @@ type Action struct { Type ActionType // Moves and Steps - ParentIdx int - ParentPosition Position - IsAttack bool + ParentClaim Claim + IsAttack bool // Moves Value common.Hash From 2ce71f083afd120e9ce42b3c6901eca6bfef3003 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 14 May 2024 09:23:23 +1000 Subject: [PATCH 7/8] op-challenger: Add backwards compatibility with v1.1.1 --- .../abis/FaultDisputeGame-1.1.1.json | 1042 +++++++++++++++++ .../game/fault/contracts/faultdisputegame.go | 10 + .../fault/contracts/faultdisputegame111.go | 28 + .../fault/contracts/faultdisputegame_test.go | 11 +- 4 files changed, 1089 insertions(+), 2 deletions(-) create mode 100644 op-challenger/game/fault/contracts/abis/FaultDisputeGame-1.1.1.json create mode 100644 op-challenger/game/fault/contracts/faultdisputegame111.go diff --git a/op-challenger/game/fault/contracts/abis/FaultDisputeGame-1.1.1.json b/op-challenger/game/fault/contracts/abis/FaultDisputeGame-1.1.1.json new file mode 100644 index 0000000000000..f0558ad5961b4 --- /dev/null +++ b/op-challenger/game/fault/contracts/abis/FaultDisputeGame-1.1.1.json @@ -0,0 +1,1042 @@ +[ + { + "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" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "absolutePrestate", + "outputs": [ + { + "internalType": "Claim", + "name": "absolutePrestate_", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_ident", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_execLeafIdx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_partOffset", + "type": "uint256" + } + ], + "name": "addLocalData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "anchorStateRegistry", + "outputs": [ + { + "internalType": "contract IAnchorStateRegistry", + "name": "registry_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_parentIndex", + "type": "uint256" + }, + { + "internalType": "Claim", + "name": "_claim", + "type": "bytes32" + } + ], + "name": "attack", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "version", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "stateRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "messagePasserStorageRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "latestBlockhash", + "type": "bytes32" + } + ], + "internalType": "struct Types.OutputRootProof", + "name": "_outputRootProof", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "_headerRLP", + "type": "bytes" + } + ], + "name": "challengeRootL2Block", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "claimCredit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "claimData", + "outputs": [ + { + "internalType": "uint32", + "name": "parentIndex", + "type": "uint32" + }, + { + "internalType": "address", + "name": "counteredBy", + "type": "address" + }, + { + "internalType": "address", + "name": "claimant", + "type": "address" + }, + { + "internalType": "uint128", + "name": "bond", + "type": "uint128" + }, + { + "internalType": "Claim", + "name": "claim", + "type": "bytes32" + }, + { + "internalType": "Position", + "name": "position", + "type": "uint128" + }, + { + "internalType": "Clock", + "name": "clock", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claimDataLen", + "outputs": [ + { + "internalType": "uint256", + "name": "len_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Hash", + "name": "", + "type": "bytes32" + } + ], + "name": "claims", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clockExtension", + "outputs": [ + { + "internalType": "Duration", + "name": "clockExtension_", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "createdAt", + "outputs": [ + { + "internalType": "Timestamp", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "credit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_parentIndex", + "type": "uint256" + }, + { + "internalType": "Claim", + "name": "_claim", + "type": "bytes32" + } + ], + "name": "defend", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "extraData", + "outputs": [ + { + "internalType": "bytes", + "name": "extraData_", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "gameCreator", + "outputs": [ + { + "internalType": "address", + "name": "creator_", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "gameData", + "outputs": [ + { + "internalType": "GameType", + "name": "gameType_", + "type": "uint32" + }, + { + "internalType": "Claim", + "name": "rootClaim_", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "extraData_", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gameType", + "outputs": [ + { + "internalType": "GameType", + "name": "gameType_", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_claimIndex", + "type": "uint256" + } + ], + "name": "getChallengerDuration", + "outputs": [ + { + "internalType": "Duration", + "name": "duration_", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_claimIndex", + "type": "uint256" + } + ], + "name": "getNumToResolve", + "outputs": [ + { + "internalType": "uint256", + "name": "numRemainingChildren_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Position", + "name": "_position", + "type": "uint128" + } + ], + "name": "getRequiredBond", + "outputs": [ + { + "internalType": "uint256", + "name": "requiredBond_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Head", + "outputs": [ + { + "internalType": "Hash", + "name": "l1Head_", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "l2BlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "l2BlockNumber_", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "l2BlockNumberChallenged", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2BlockNumberChallenger", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2ChainId", + "outputs": [ + { + "internalType": "uint256", + "name": "l2ChainId_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxClockDuration", + "outputs": [ + { + "internalType": "Duration", + "name": "maxClockDuration_", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxGameDepth", + "outputs": [ + { + "internalType": "uint256", + "name": "maxGameDepth_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_challengeIndex", + "type": "uint256" + }, + { + "internalType": "Claim", + "name": "_claim", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "_isAttack", + "type": "bool" + } + ], + "name": "move", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "resolutionCheckpoints", + "outputs": [ + { + "internalType": "bool", + "name": "initialCheckpointComplete", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "subgameIndex", + "type": "uint32" + }, + { + "internalType": "Position", + "name": "leftmostPosition", + "type": "uint128" + }, + { + "internalType": "address", + "name": "counteredBy", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "resolve", + "outputs": [ + { + "internalType": "enum GameStatus", + "name": "status_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_claimIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_numToResolve", + "type": "uint256" + } + ], + "name": "resolveClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resolvedAt", + "outputs": [ + { + "internalType": "Timestamp", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "resolvedSubgames", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rootClaim", + "outputs": [ + { + "internalType": "Claim", + "name": "rootClaim_", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "splitDepth", + "outputs": [ + { + "internalType": "uint256", + "name": "splitDepth_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startingBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "startingBlockNumber_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startingOutputRoot", + "outputs": [ + { + "internalType": "Hash", + "name": "root", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "l2BlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startingRootHash", + "outputs": [ + { + "internalType": "Hash", + "name": "startingRootHash_", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "enum GameStatus", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_claimIndex", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "_isAttack", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "_stateData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_proof", + "type": "bytes" + } + ], + "name": "step", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "subgames", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vm", + "outputs": [ + { + "internalType": "contract IBigStepper", + "name": "vm_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "contract IDelayedWETH", + "name": "weth_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "parentIndex", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "Claim", + "name": "claim", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "claimant", + "type": "address" + } + ], + "name": "Move", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "enum GameStatus", + "name": "status", + "type": "uint8" + } + ], + "name": "Resolved", + "type": "event" + }, + { + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "AnchorRootNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "BlockNumberMatches", + "type": "error" + }, + { + "inputs": [], + "name": "BondTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "CannotDefendRootClaim", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimAboveSplit", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimAlreadyResolved", + "type": "error" + }, + { + "inputs": [], + "name": "ClockNotExpired", + "type": "error" + }, + { + "inputs": [], + "name": "ClockTimeExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ContentLengthMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateStep", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyItem", + "type": "error" + }, + { + "inputs": [], + "name": "GameDepthExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "GameNotInProgress", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectBondAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClockExtension", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataRemainder", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidHeader", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidHeaderRLP", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLocalIdent", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOutputRootProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidParent", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPrestate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSplitDepth", + "type": "error" + }, + { + "inputs": [], + "name": "L2BlockNumberChallenged", + "type": "error" + }, + { + "inputs": [], + "name": "MaxDepthTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "NoCreditToClaim", + "type": "error" + }, + { + "inputs": [], + "name": "OutOfOrderResolution", + "type": "error" + }, + { + "inputs": [], + "name": "UnexpectedList", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "Claim", + "name": "rootClaim", + "type": "bytes32" + } + ], + "name": "UnexpectedRootClaim", + "type": "error" + }, + { + "inputs": [], + "name": "UnexpectedString", + "type": "error" + }, + { + "inputs": [], + "name": "ValidStep", + "type": "error" + } +] \ No newline at end of file diff --git a/op-challenger/game/fault/contracts/faultdisputegame.go b/op-challenger/game/fault/contracts/faultdisputegame.go index 64c93d19d4da3..6ad0b1ef891b5 100644 --- a/op-challenger/game/fault/contracts/faultdisputegame.go +++ b/op-challenger/game/fault/contracts/faultdisputegame.go @@ -109,6 +109,16 @@ func NewFaultDisputeGameContract(ctx context.Context, metrics metrics.ContractMe contract: batching.NewBoundContract(legacyAbi, addr), }, }, nil + } else if strings.HasPrefix(version, "1.1.") { + // Detected an older version of contracts, use a compatibility shim. + legacyAbi := mustParseAbi(faultDisputeGameAbi111) + return &FaultDisputeGameContract111{ + FaultDisputeGameContractLatest: FaultDisputeGameContractLatest{ + metrics: metrics, + multiCaller: caller, + contract: batching.NewBoundContract(legacyAbi, addr), + }, + }, nil } else { return &FaultDisputeGameContractLatest{ metrics: metrics, diff --git a/op-challenger/game/fault/contracts/faultdisputegame111.go b/op-challenger/game/fault/contracts/faultdisputegame111.go new file mode 100644 index 0000000000000..6e46bfdc12309 --- /dev/null +++ b/op-challenger/game/fault/contracts/faultdisputegame111.go @@ -0,0 +1,28 @@ +package contracts + +import ( + "context" + _ "embed" + "math/big" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" +) + +//go:embed abis/FaultDisputeGame-1.1.1.json +var faultDisputeGameAbi111 []byte + +type FaultDisputeGameContract111 struct { + FaultDisputeGameContractLatest +} + +func (f *FaultDisputeGameContract111) AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) { + call := f.contract.Call(methodAttack, big.NewInt(int64(parent.ContractIndex)), pivot) + return f.txWithBond(ctx, parent.Position.Attack(), call) +} + +func (f *FaultDisputeGameContract111) DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error) { + call := f.contract.Call(methodDefend, big.NewInt(int64(parent.ContractIndex)), pivot) + return f.txWithBond(ctx, parent.Position.Defend(), call) +} diff --git a/op-challenger/game/fault/contracts/faultdisputegame_test.go b/op-challenger/game/fault/contracts/faultdisputegame_test.go index 65e49cb6e1637..4864b223d4c51 100644 --- a/op-challenger/game/fault/contracts/faultdisputegame_test.go +++ b/op-challenger/game/fault/contracts/faultdisputegame_test.go @@ -45,6 +45,7 @@ func (c contractVersion) Is(versions ...string) bool { const ( vers080 = "0.8.0" vers0180 = "0.18.0" + vers111 = "1.1.1" versLatest = "1.2.0" ) @@ -61,6 +62,12 @@ var versions = []contractVersion{ return mustParseAbi(faultDisputeGameAbi0180) }, }, + { + version: vers111, + loadAbi: func() *abi.ABI { + return mustParseAbi(faultDisputeGameAbi111) + }, + }, { version: versLatest, loadAbi: snapshots.LoadFaultDisputeGameABI, @@ -388,7 +395,7 @@ func TestAttackTx(t *testing.T) { value := common.Hash{0xaa} parent := faultTypes.Claim{ClaimData: faultTypes.ClaimData{Value: common.Hash{0xbb}}, ContractIndex: 111} stubRpc.SetResponse(fdgAddr, methodRequiredBond, rpcblock.Latest, []interface{}{parent.Position.Attack().ToGIndex()}, []interface{}{bond}) - if version.Is(vers080, vers0180) { + if version.Is(vers080, vers0180, vers111) { stubRpc.SetResponse(fdgAddr, methodAttack, rpcblock.Latest, []interface{}{big.NewInt(111), value}, nil) } else { stubRpc.SetResponse(fdgAddr, methodAttack, rpcblock.Latest, []interface{}{parent.Value, big.NewInt(111), value}, nil) @@ -410,7 +417,7 @@ func TestDefendTx(t *testing.T) { value := common.Hash{0xaa} parent := faultTypes.Claim{ClaimData: faultTypes.ClaimData{Value: common.Hash{0xbb}}, ContractIndex: 111} stubRpc.SetResponse(fdgAddr, methodRequiredBond, rpcblock.Latest, []interface{}{parent.Position.Defend().ToGIndex()}, []interface{}{bond}) - if version.Is(vers080, vers0180) { + if version.Is(vers080, vers0180, vers111) { stubRpc.SetResponse(fdgAddr, methodDefend, rpcblock.Latest, []interface{}{big.NewInt(111), value}, nil) } else { stubRpc.SetResponse(fdgAddr, methodDefend, rpcblock.Latest, []interface{}{parent.Value, big.NewInt(111), value}, nil) From 9940317e9f9ef2d6d7502cffeb856654ebf68bf5 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 14 May 2024 09:46:25 +1000 Subject: [PATCH 8/8] op-e2e: Update e2e for new FaultDisputeGame ABI --- op-bindings/bindings/faultdisputegame.go | 179 ++++++++++++------ .../fault/contracts/faultdisputegame080.go | 1 + .../disputegame/output_game_helper.go | 4 +- 3 files changed, 123 insertions(+), 61 deletions(-) diff --git a/op-bindings/bindings/faultdisputegame.go b/op-bindings/bindings/faultdisputegame.go index f1473b37bc4cf..d43287d3da6af 100644 --- a/op-bindings/bindings/faultdisputegame.go +++ b/op-bindings/bindings/faultdisputegame.go @@ -30,35 +30,13 @@ var ( // FaultDisputeGameMetaData contains all meta data concerning the FaultDisputeGame contract. var FaultDisputeGameMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"_absolutePrestate\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_maxGameDepth\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_splitDepth\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_clockExtension\",\"type\":\"uint64\",\"internalType\":\"Duration\"},{\"name\":\"_maxClockDuration\",\"type\":\"uint64\",\"internalType\":\"Duration\"},{\"name\":\"_vm\",\"type\":\"address\",\"internalType\":\"contractIBigStepper\"},{\"name\":\"_weth\",\"type\":\"address\",\"internalType\":\"contractIDelayedWETH\"},{\"name\":\"_anchorStateRegistry\",\"type\":\"address\",\"internalType\":\"contractIAnchorStateRegistry\"},{\"name\":\"_l2ChainId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"absolutePrestate\",\"inputs\":[],\"outputs\":[{\"name\":\"absolutePrestate_\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addLocalData\",\"inputs\":[{\"name\":\"_ident\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_execLeafIdx\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"anchorStateRegistry\",\"inputs\":[],\"outputs\":[{\"name\":\"registry_\",\"type\":\"address\",\"internalType\":\"contractIAnchorStateRegistry\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"attack\",\"inputs\":[{\"name\":\"_parentIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"claimCredit\",\"inputs\":[{\"name\":\"_recipient\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"claimData\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"parentIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"counteredBy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"bond\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"position\",\"type\":\"uint128\",\"internalType\":\"Position\"},{\"name\":\"clock\",\"type\":\"uint128\",\"internalType\":\"Clock\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claimDataLen\",\"inputs\":[],\"outputs\":[{\"name\":\"len_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claims\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"ClaimHash\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clockExtension\",\"inputs\":[],\"outputs\":[{\"name\":\"clockExtension_\",\"type\":\"uint64\",\"internalType\":\"Duration\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createdAt\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"credit\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"defend\",\"inputs\":[{\"name\":\"_parentIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"extraData\",\"inputs\":[],\"outputs\":[{\"name\":\"extraData_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"gameCreator\",\"inputs\":[],\"outputs\":[{\"name\":\"creator_\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"gameData\",\"inputs\":[],\"outputs\":[{\"name\":\"gameType_\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"rootClaim_\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"extraData_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gameType\",\"inputs\":[],\"outputs\":[{\"name\":\"gameType_\",\"type\":\"uint32\",\"internalType\":\"GameType\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getChallengerDuration\",\"inputs\":[{\"name\":\"_claimIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"duration_\",\"type\":\"uint64\",\"internalType\":\"Duration\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNumToResolve\",\"inputs\":[{\"name\":\"_claimIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"numRemainingChildren_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRequiredBond\",\"inputs\":[{\"name\":\"_position\",\"type\":\"uint128\",\"internalType\":\"Position\"}],\"outputs\":[{\"name\":\"requiredBond_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"l1Head\",\"inputs\":[],\"outputs\":[{\"name\":\"l1Head_\",\"type\":\"bytes32\",\"internalType\":\"Hash\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"l2BlockNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"l2BlockNumber_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"l2ChainId\",\"inputs\":[],\"outputs\":[{\"name\":\"l2ChainId_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxClockDuration\",\"inputs\":[],\"outputs\":[{\"name\":\"maxClockDuration_\",\"type\":\"uint64\",\"internalType\":\"Duration\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGameDepth\",\"inputs\":[],\"outputs\":[{\"name\":\"maxGameDepth_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"move\",\"inputs\":[{\"name\":\"_challengeIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_isAttack\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"resolutionCheckpoints\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"initialCheckpointComplete\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"subgameIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"leftmostPosition\",\"type\":\"uint128\",\"internalType\":\"Position\"},{\"name\":\"counteredBy\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"resolve\",\"inputs\":[],\"outputs\":[{\"name\":\"status_\",\"type\":\"uint8\",\"internalType\":\"enumGameStatus\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resolveClaim\",\"inputs\":[{\"name\":\"_claimIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_numToResolve\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resolvedAt\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"resolvedSubgames\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"rootClaim\",\"inputs\":[],\"outputs\":[{\"name\":\"rootClaim_\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"splitDepth\",\"inputs\":[],\"outputs\":[{\"name\":\"splitDepth_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"startingBlockNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"startingBlockNumber_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"startingOutputRoot\",\"inputs\":[],\"outputs\":[{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"Hash\"},{\"name\":\"l2BlockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"startingRootHash\",\"inputs\":[],\"outputs\":[{\"name\":\"startingRootHash_\",\"type\":\"bytes32\",\"internalType\":\"Hash\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"status\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumGameStatus\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"step\",\"inputs\":[{\"name\":\"_claimIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_isAttack\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"_stateData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"subgames\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"vm\",\"inputs\":[],\"outputs\":[{\"name\":\"vm_\",\"type\":\"address\",\"internalType\":\"contractIBigStepper\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"weth\",\"inputs\":[],\"outputs\":[{\"name\":\"weth_\",\"type\":\"address\",\"internalType\":\"contractIDelayedWETH\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"Move\",\"inputs\":[{\"name\":\"parentIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"claim\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"Claim\"},{\"name\":\"claimant\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Resolved\",\"inputs\":[{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumGameStatus\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AnchorRootNotFound\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BondTransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CannotDefendRootClaim\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClaimAboveSplit\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClaimAlreadyExists\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClaimAlreadyResolved\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClockNotExpired\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClockTimeExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DuplicateStep\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"GameDepthExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"GameNotInProgress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IncorrectBondAmount\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidClockExtension\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidLocalIdent\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidParent\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPrestate\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSplitDepth\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"MaxDepthTooLarge\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoCreditToClaim\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OutOfOrderResolution\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedRootClaim\",\"inputs\":[{\"name\":\"rootClaim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}]},{\"type\":\"error\",\"name\":\"ValidStep\",\"inputs\":[]}]", - Bin: "0x6101c06040523480156200001257600080fd5b506040516200511438038062005114833981016040819052620000359162000187565b620000436001607e62000248565b60ff168811156200006757604051633beff19960e11b815260040160405180910390fd5b878710620000885760405163e62ccf3960e01b815260040160405180910390fd5b620000a7856001600160401b03166200014e60201b620030381760201c565b6001600160401b0316620000cf876001600160401b03166200014e60201b620030381760201c565b6001600160401b03161115620000f85760405163235dfb2b60e21b815260040160405180910390fd5b63ffffffff9099166101205260809790975260a09590955260c0939093526001600160401b039182166101a0521660e0526001600160a01b0390811661010052908116610140521661016052610180526200027a565b90565b80516001600160401b03811681146200016957600080fd5b919050565b6001600160a01b03811681146200018457600080fd5b50565b6000806000806000806000806000806101408b8d031215620001a857600080fd5b8a5163ffffffff81168114620001bd57600080fd5b809a505060208b0151985060408b0151975060608b01519650620001e460808c0162000151565b9550620001f460a08c0162000151565b945060c08b015162000206816200016e565b60e08c015190945062000219816200016e565b6101008c01519093506200022d816200016e565b809250506101208b015190509295989b9194979a5092959850565b600060ff821660ff8416808210156200027157634e487b7160e01b600052601160045260246000fd5b90039392505050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a051614d22620003f26000396000818161061c0152818161198401528181611a420152611a6c01526000818161096c01526132890152600081816105610152818161131a0152611f95015260008181610488015281816114da01528181611e3c0152818161239601526134170152600081816107c801528181611f54015261331801526000818161045501528181612bfa0152612f4f0152600081816109bf01528181610b9d0152818161191e015281816119af01528181611aa4015281816125a201526125e40152600081816109f2015281816117c40152818161188d01528181611a0d01528181612a4d015281816131510152818161351601528181613c3c01528181613d6a01528181613e6b0152613f40015260008181610aa901528181611830015281816126b201528181612738015281816129430152612a6e0152600081816106c10152612b0c0152614d226000f3fe6080604052600436106102d15760003560e01c80638980e0cc11610179578063cf09e0d0116100d6578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610a76578063fa315aa914610a9a578063fe2bbeb214610acd57600080fd5b8063ec5e6308146109e3578063eff0f59214610a16578063f8f43ff614610a5657600080fd5b8063d6ae3cd5116100bb578063d6ae3cd51461095d578063d8cc1a3c14610990578063dabd396d146109b057600080fd5b8063cf09e0d01461090f578063d5d44d801461093057600080fd5b8063bcef3b551161012d578063c395e1ca11610112578063c395e1ca14610852578063c55cd0c714610872578063c6f0308c1461088557600080fd5b8063bcef3b55146107f2578063bd8da9561461083257600080fd5b80638d450a951161015e5780638d450a95146106b2578063a445ece6146106e5578063bbdc02db146107b157600080fd5b80638980e0cc1461065d5780638b85902b1461067257600080fd5b806354fd4d501161023257806360e27464116101e65780636b6716c0116101c05780636b6716c01461060d57806370872aa5146106405780638129fc1c1461065557600080fd5b806360e274641461059a578063632247ea146105ba5780636361506d146105cd57600080fd5b80635a5fa2d9116102175780635a5fa2d9146105325780635c0cba3314610552578063609d33341461058557600080fd5b806354fd4d50146104ac57806357da950e1461050257600080fd5b80632ad69aeb1161028957806337b1b2291161026e57806337b1b229146103e55780633a768463146104465780633fc8cef31461047957600080fd5b80632ad69aeb146103b257806335fef567146103d257600080fd5b8063200d2ed2116102ba578063200d2ed21461034357806325fc2ace1461037e5780632810e1d61461039d57600080fd5b806303c2924d146102d657806319effeb4146102f8575b600080fd5b3480156102e257600080fd5b506102f66102f136600461459e565b610afd565b005b34801561030457600080fd5b506000546103259068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561034f57600080fd5b5060005461037190700100000000000000000000000000000000900460ff1681565b60405161033a91906145ef565b34801561038a57600080fd5b506007545b60405190815260200161033a565b3480156103a957600080fd5b506103716110f6565b3480156103be57600080fd5b5061038f6103cd36600461459e565b61139b565b6102f66103e036600461459e565b6113cc565b3480156103f157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c5b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161033a565b34801561045257600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610421565b34801561048557600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610421565b3480156104b857600080fd5b506104f56040518060400160405280600681526020017f302e31382e30000000000000000000000000000000000000000000000000000081525081565b60405161033a919061469b565b34801561050e57600080fd5b5060075460085461051d919082565b6040805192835260208301919091520161033a565b34801561053e57600080fd5b5061038f61054d3660046146ae565b6113e1565b34801561055e57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610421565b34801561059157600080fd5b506104f561141b565b3480156105a657600080fd5b506102f66105b53660046146ec565b611429565b6102f66105c8366004614725565b6115d5565b3480156105d957600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013561038f565b34801561061957600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610325565b34801561064c57600080fd5b5060085461038f565b6102f6611ed5565b34801561066957600080fd5b5060015461038f565b34801561067e57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561038f565b3480156106be57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061038f565b3480156106f157600080fd5b5061075d6107003660046146ae565b6006602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161033a565b3480156107bd57600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161033a565b3480156107fe57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013561038f565b34801561083e57600080fd5b5061032561084d3660046146ae565b61242d565b34801561085e57600080fd5b5061038f61086d36600461475a565b61260c565b6102f661088036600461459e565b6127ef565b34801561089157600080fd5b506108a56108a03660046146ae565b6127fb565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161033a565b34801561091b57600080fd5b506000546103259067ffffffffffffffff1681565b34801561093c57600080fd5b5061038f61094b3660046146ec565b60026020526000908152604090205481565b34801561096957600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061038f565b34801561099c57600080fd5b506102f66109ab3660046147d5565b612892565b3480156109bc57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610325565b3480156109ef57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061038f565b348015610a2257600080fd5b50610a46610a313660046146ae565b60036020526000908152604090205460ff1681565b604051901515815260200161033a565b348015610a6257600080fd5b506102f6610a7136600461485f565b612ec1565b348015610a8257600080fd5b50610a8b613316565b60405161033a9392919061488b565b348015610aa657600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061038f565b348015610ad957600080fd5b50610a46610ae83660046146ae565b60056020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610b2957610b296145c0565b14610b60576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060018381548110610b7557610b756148b0565b906000526020600020906005020190506000610b908461242d565b905067ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081169082161015610bf9576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526005602052604090205460ff1615610c42576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000848152600460205260409020805480158015610c5f57508515155b15610cfa578354640100000000900473ffffffffffffffffffffffffffffffffffffffff1660008115610c925781610cae565b600186015473ffffffffffffffffffffffffffffffffffffffff165b9050610cba8187613376565b50505060009485525050600560205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600660209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152610d9d576fffffffffffffffffffffffffffffffff6040820152600181526000869003610d9d578195505b600086826020015163ffffffff16610db5919061490e565b90506000838211610dc65781610dc8565b835b602084015190915063ffffffff165b81811015610f14576000868281548110610df357610df36148b0565b6000918252602080832090910154808352600590915260409091205490915060ff16610e4b576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060018281548110610e6057610e606148b0565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff16158015610ebd5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b15610eff57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b50508080610f0c90614926565b915050610dd7565b5063ffffffff818116602085810191825260008c81526006909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036110eb57606083015187547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff831690810291909117895560008b815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556110e990156110c757816110e3565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613376565b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611124576111246145c0565b1461115b576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260056020527f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc5460ff166111bf576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660016000815481106111eb576111eb6148b0565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611226576001611229565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156112da576112da6145c0565b0217905560028111156112ef576112ef6145c0565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561138057600080fd5b505af1158015611394573d6000803e3d6000fd5b5050505090565b600460205281600052604060002081815481106113b757600080fd5b90600052602060002001600091509150505481565b6113d8828260006115d5565b5050565b905090565b6000818152600660209081526040808320600490925282208054825461141290610100900463ffffffff168261495e565b95945050505050565b60606113dc60546020613478565b73ffffffffffffffffffffffffffffffffffffffff811660009081526002602052604081208054908290559081900361148e576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063f3fef3a390604401600060405180830381600087803b15801561151e57600080fd5b505af1158015611532573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611590576040519150601f19603f3d011682016040523d82523d6000602084013e611595565b606091505b50509050806115d0576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60008054700100000000000000000000000000000000900460ff166002811115611601576116016145c0565b14611638576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001848154811061164d5761164d6148b0565b600091825260208083206040805160e0810182526005909402909101805463ffffffff808216865273ffffffffffffffffffffffffffffffffffffffff6401000000009092048216948601949094526001820154169184019190915260028101546fffffffffffffffffffffffffffffffff90811660608501526003820154608085015260049091015480821660a0850181905270010000000000000000000000000000000090910490911660c084015291935090919061171290839086906134ca16565b905060006117b2826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508615806117ed57506117ea7f0000000000000000000000000000000000000000000000000000000000000000600261490e565b81145b80156117f7575084155b1561182e576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000811115611888576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118b37f0000000000000000000000000000000000000000000000000000000000000000600161490e565b81036118c5576118c5868885886134d2565b346118cf8361260c565b14611906576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006119118861242d565b905067ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811690821603611979576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001667ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166119d99190614975565b67ffffffffffffffff166119f48267ffffffffffffffff1690565b67ffffffffffffffff161115611ad6576000611a3160017f000000000000000000000000000000000000000000000000000000000000000061495e565b8314611a675767ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016611a9c565b611a9c7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16600261499e565b9050611ad2817f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16614975565b9150505b6000604082901b42176000898152608086901b6fffffffffffffffffffffffffffffffff8c1617602052604081209192509060008181526003602052604090205490915060ff1615611b54576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016003600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060016040518060e001604052808c63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018b8152602001876fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600460008b815260200190815260200160002060018080549050611de9919061495e565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263d0e30db09234926004808301939282900301818588803b158015611e8157600080fd5b505af1158015611e95573d6000803e3d6000fd5b50506040513393508c92508d91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a450505050505050505050565b60005471010000000000000000000000000000000000900460ff1615611f27576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690637258a807906024016040805180830381865afa158015611fdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fff91906149ce565b90925090508161203b576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526007829055600881905536607a1461206e57639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013511612108576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c0190815282548084018455928a529a5160059092027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf681018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf787018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf8860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf985015551955182167001000000000000000000000000000000000295909116949094177fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfa9091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f00000000000000000000000000000000000000000000000000000000000000009092169363d0e30db093926004828101939282900301818588803b1580156123dc57600080fd5b505af11580156123f0573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff16600281111561245b5761245b6145c0565b14612492576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600183815481106124a7576124a76148b0565b600091825260208220600590910201805490925063ffffffff9081161461251657815460018054909163ffffffff169081106124e5576124e56148b0565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b600482015460009061254e90700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b6125629067ffffffffffffffff164261495e565b612581612541846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612595919061490e565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001667ffffffffffffffff168167ffffffffffffffff16116125e25780611412565b7f000000000000000000000000000000000000000000000000000000000000000095945050505050565b6000806126ab836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f000000000000000000000000000000000000000000000000000000000000000081111561270a576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a30060006127258383614a21565b9050670de0b6b3a7640000600061275c827f0000000000000000000000000000000000000000000000000000000000000000614a35565b9050600061277a612775670de0b6b3a764000086614a35565b613683565b9050600061278884846138de565b90506000612796838361392d565b905060006127a38261395b565b905060006127c2826127bd670de0b6b3a76400008f614a35565b613b43565b905060006127d08b8361392d565b90506127dc818d614a35565b9f9e505050505050505050505050505050565b6113d8828260016115d5565b6001818154811061280b57600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff1660028111156128be576128be6145c0565b146128f5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001878154811061290a5761290a6148b0565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506129697f0000000000000000000000000000000000000000000000000000000000000000600161490e565b612a05826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614612a3f576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808915612b3657612a927f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061495e565b6001901b612ab1846fffffffffffffffffffffffffffffffff16613b7d565b6fffffffffffffffffffffffffffffffff16612acd9190614a72565b15612b0a57612b01612af260016fffffffffffffffffffffffffffffffff8716614a86565b865463ffffffff166000613c1c565b60030154612b2c565b7f00000000000000000000000000000000000000000000000000000000000000005b9150849050612b60565b60038501549150612b5d612af26fffffffffffffffffffffffffffffffff86166001614aaf565b90505b600882901b60088a8a604051612b77929190614ae3565b6040518091039020901b14612bb8576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612bc38c613d00565b90506000612bd2836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e14ced3290612c4c908f908f908f908f908a90600401614b3c565b6020604051808303816000875af1158015612c6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8f9190614b76565b600485015491149150600090600290612d3a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b612dd6896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b612de09190614b8f565b612dea9190614bb2565b60ff161590508115158103612e2b576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff1615612e82576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff166002811115612eed57612eed6145c0565b14612f24576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600080612f3386613d2f565b93509350935093506000612f4985858585614138565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fdc9190614bd4565b9050600189036130d75773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461303b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b90565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156130ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130d19190614b76565b506110eb565b600289036131035773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961303b565b6003890361312f5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761303b565b6004890361324b5760006131756fffffffffffffffffffffffffffffffff85167f00000000000000000000000000000000000000000000000000000000000000006141f2565b600854613182919061490e565b61318d90600161490e565b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af1158015613220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132449190614b76565b50506110eb565b600589036132e4576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000000060c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a40161308e565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360140135606061336f61141b565b9050909192565b60028082015473ffffffffffffffffffffffffffffffffffffffff841660009081526020929092526040822080546fffffffffffffffffffffffffffffffff9092169283926133c690849061490e565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f00000000000000000000000000000000000000000000000000000000000000001690637eee288d90604401600060405180830381600087803b15801561345b57600080fd5b505af115801561346f573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b151760011b90565b60006134f16fffffffffffffffffffffffffffffffff84166001614aaf565b9050600061350182866001613c1c565b9050600086901a83806135ed575061353a60027f0000000000000000000000000000000000000000000000000000000000000000614a72565b60048301546002906135de906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6135e89190614bb2565b60ff16145b156136455760ff811660011480613607575060ff81166002145b613640576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016120ff565b61346f565b60ff81161561346f576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016120ff565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136136e257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261391b57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b60008160001904831182021561394b5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361398957919050565b680755bf798b4a1bf1e582126139a75763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613b74670de0b6b3a764000083613b5b86613683565b613b659190614bf1565b613b6f9190614cad565b61395b565b90505b92915050565b600080613c0a837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b60008082613c6557613c606fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000006142a0565b613c80565b613c80856fffffffffffffffffffffffffffffffff16614450565b905060018481548110613c9557613c956148b0565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff828116911614613cf857815460018054909163ffffffff16908110613ce357613ce36148b0565b90600052602060002090600502019150613ca6565b509392505050565b6000806000806000613d1186613d2f565b9350935093509350613d2584848484614138565b9695505050505050565b6000806000806000859050600060018281548110613d4f57613d4f6148b0565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000090613e26906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613e60576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000090613f27906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169250821115613f9c57825463ffffffff16613f667f0000000000000000000000000000000000000000000000000000000000000000600161490e565b8303613f70578391505b60018181548110613f8357613f836148b0565b9060005260206000209060050201935080945050613e64565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff16614005613ff0856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1614905080156140d457600061403d836fffffffffffffffffffffffffffffffff16613b7d565b6fffffffffffffffffffffffffffffffff1611156140a857600061407f61407760016fffffffffffffffffffffffffffffffff8616614a86565b896001613c1c565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506140ae9050565b6007549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff16975061412a565b60006140f66140776fffffffffffffffffffffffffffffffff85166001614aaf565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff8416156141a55760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611412565b82826040516020016141d39291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b60008061427f847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008161433f846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614379576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61438283614450565b905081614421826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613b7757613b7461443783600161490e565b6fffffffffffffffffffffffffffffffff8316906144f5565b600081196001830116816144e4827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b600080614582847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b600080604083850312156145b157600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061462a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000815180845260005b818110156146565760208185018101518683018201520161463a565b81811115614668576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613b746020830184614630565b6000602082840312156146c057600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146146e957600080fd5b50565b6000602082840312156146fe57600080fd5b8135614709816146c7565b9392505050565b8035801515811461472057600080fd5b919050565b60008060006060848603121561473a57600080fd5b833592506020840135915061475160408501614710565b90509250925092565b60006020828403121561476c57600080fd5b81356fffffffffffffffffffffffffffffffff8116811461470957600080fd5b60008083601f84011261479e57600080fd5b50813567ffffffffffffffff8111156147b657600080fd5b6020830191508360208285010111156147ce57600080fd5b9250929050565b600080600080600080608087890312156147ee57600080fd5b863595506147fe60208801614710565b9450604087013567ffffffffffffffff8082111561481b57600080fd5b6148278a838b0161478c565b9096509450606089013591508082111561484057600080fd5b5061484d89828a0161478c565b979a9699509497509295939492505050565b60008060006060848603121561487457600080fd5b505081359360208301359350604090920135919050565b63ffffffff841681528260208201526060604082015260006114126060830184614630565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115614921576149216148df565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614957576149576148df565b5060010190565b600082821015614970576149706148df565b500390565b600067ffffffffffffffff83811690831681811015614996576149966148df565b039392505050565b600067ffffffffffffffff808316818516818304811182151516156149c5576149c56148df565b02949350505050565b600080604083850312156149e157600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614a3057614a306149f2565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614a6d57614a6d6148df565b500290565b600082614a8157614a816149f2565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015614996576149966148df565b60006fffffffffffffffffffffffffffffffff808316818516808303821115614ada57614ada6148df565b01949350505050565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000614b50606083018789614af3565b8281036020840152614b63818688614af3565b9150508260408301529695505050505050565b600060208284031215614b8857600080fd5b5051919050565b600060ff821660ff841680821015614ba957614ba96148df565b90039392505050565b600060ff831680614bc557614bc56149f2565b8060ff84160691505092915050565b600060208284031215614be657600080fd5b8151614709816146c7565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615614c3257614c326148df565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615614c6d57614c6d6148df565b60008712925087820587128484161615614c8957614c896148df565b87850587128184161615614c9f57614c9f6148df565b505050929093029392505050565b600082614cbc57614cbc6149f2565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615614d1057614d106148df565b50059056fea164736f6c634300080f000a", + ABI: "[{\"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\":\"contractIBigStepper\",\"name\":\"_vm\",\"type\":\"address\"},{\"internalType\":\"contractIDelayedWETH\",\"name\":\"_weth\",\"type\":\"address\"},{\"internalType\":\"contractIAnchorStateRegistry\",\"name\":\"_anchorStateRegistry\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_l2ChainId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"absolutePrestate\",\"outputs\":[{\"internalType\":\"Claim\",\"name\":\"absolutePrestate_\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ident\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_execLeafIdx\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_partOffset\",\"type\":\"uint256\"}],\"name\":\"addLocalData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"anchorStateRegistry\",\"outputs\":[{\"internalType\":\"contractIAnchorStateRegistry\",\"name\":\"registry_\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"Claim\",\"name\":\"_disputed\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_parentIndex\",\"type\":\"uint256\"},{\"internalType\":\"Claim\",\"name\":\"_claim\",\"type\":\"bytes32\"}],\"name\":\"attack\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messagePasserStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structTypes.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_headerRLP\",\"type\":\"bytes\"}],\"name\":\"challengeRootL2Block\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"claimCredit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"claimData\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"parentIndex\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"counteredBy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"claimant\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"bond\",\"type\":\"uint128\"},{\"internalType\":\"Claim\",\"name\":\"claim\",\"type\":\"bytes32\"},{\"internalType\":\"Position\",\"name\":\"position\",\"type\":\"uint128\"},{\"internalType\":\"Clock\",\"name\":\"clock\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimDataLen\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"len_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"Hash\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"claims\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clockExtension\",\"outputs\":[{\"internalType\":\"Duration\",\"name\":\"clockExtension_\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"createdAt\",\"outputs\":[{\"internalType\":\"Timestamp\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"credit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"Claim\",\"name\":\"_disputed\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_parentIndex\",\"type\":\"uint256\"},{\"internalType\":\"Claim\",\"name\":\"_claim\",\"type\":\"bytes32\"}],\"name\":\"defend\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"extraData\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"extraData_\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameCreator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"creator_\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameData\",\"outputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType_\",\"type\":\"uint32\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim_\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData_\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameType\",\"outputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType_\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_claimIndex\",\"type\":\"uint256\"}],\"name\":\"getChallengerDuration\",\"outputs\":[{\"internalType\":\"Duration\",\"name\":\"duration_\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_claimIndex\",\"type\":\"uint256\"}],\"name\":\"getNumToResolve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"numRemainingChildren_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"Position\",\"name\":\"_position\",\"type\":\"uint128\"}],\"name\":\"getRequiredBond\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"requiredBond_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1Head\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"l1Head_\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"l2BlockNumber_\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockNumberChallenged\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockNumberChallenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2ChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"l2ChainId_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxClockDuration\",\"outputs\":[{\"internalType\":\"Duration\",\"name\":\"maxClockDuration_\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxGameDepth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"maxGameDepth_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"Claim\",\"name\":\"_disputed\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_challengeIndex\",\"type\":\"uint256\"},{\"internalType\":\"Claim\",\"name\":\"_claim\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"_isAttack\",\"type\":\"bool\"}],\"name\":\"move\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"resolutionCheckpoints\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"initialCheckpointComplete\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"subgameIndex\",\"type\":\"uint32\"},{\"internalType\":\"Position\",\"name\":\"leftmostPosition\",\"type\":\"uint128\"},{\"internalType\":\"address\",\"name\":\"counteredBy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"enumGameStatus\",\"name\":\"status_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_claimIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_numToResolve\",\"type\":\"uint256\"}],\"name\":\"resolveClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolvedAt\",\"outputs\":[{\"internalType\":\"Timestamp\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"resolvedSubgames\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rootClaim\",\"outputs\":[{\"internalType\":\"Claim\",\"name\":\"rootClaim_\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"splitDepth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"splitDepth_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"startingBlockNumber_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingOutputRoot\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"root\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startingRootHash\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"startingRootHash_\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"status\",\"outputs\":[{\"internalType\":\"enumGameStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_claimIndex\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_isAttack\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_stateData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_proof\",\"type\":\"bytes\"}],\"name\":\"step\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"subgames\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vm\",\"outputs\":[{\"internalType\":\"contractIBigStepper\",\"name\":\"vm_\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"weth\",\"outputs\":[{\"internalType\":\"contractIDelayedWETH\",\"name\":\"weth_\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"parentIndex\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"Claim\",\"name\":\"claim\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"claimant\",\"type\":\"address\"}],\"name\":\"Move\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"enumGameStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"name\":\"Resolved\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AnchorRootNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BlockNumberMatches\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BondTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotDefendRootClaim\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ClaimAboveSplit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ClaimAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ClaimAlreadyResolved\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ClockNotExpired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ClockTimeExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContentLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateStep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyItem\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GameDepthExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GameNotInProgress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectBondAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidClockExtension\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataRemainder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDisputedClaimIndex\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidHeader\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidHeaderRLP\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidLocalIdent\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOutputRootProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidParent\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPrestate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSplitDepth\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"L2BlockNumberChallenged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MaxDepthTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoCreditToClaim\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderResolution\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedList\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"}],\"name\":\"UnexpectedRootClaim\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedString\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValidStep\",\"type\":\"error\"}]", } // FaultDisputeGameABI is the input ABI used to generate the binding from. // Deprecated: Use FaultDisputeGameMetaData.ABI instead. var FaultDisputeGameABI = FaultDisputeGameMetaData.ABI -// FaultDisputeGameBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use FaultDisputeGameMetaData.Bin instead. -var FaultDisputeGameBin = FaultDisputeGameMetaData.Bin - -// DeployFaultDisputeGame deploys a new Ethereum contract, binding an instance of FaultDisputeGame to it. -func DeployFaultDisputeGame(auth *bind.TransactOpts, backend bind.ContractBackend, _gameType uint32, _absolutePrestate [32]byte, _maxGameDepth *big.Int, _splitDepth *big.Int, _clockExtension uint64, _maxClockDuration uint64, _vm common.Address, _weth common.Address, _anchorStateRegistry common.Address, _l2ChainId *big.Int) (common.Address, *types.Transaction, *FaultDisputeGame, error) { - parsed, err := FaultDisputeGameMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(FaultDisputeGameBin), backend, _gameType, _absolutePrestate, _maxGameDepth, _splitDepth, _clockExtension, _maxClockDuration, _vm, _weth, _anchorStateRegistry, _l2ChainId) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &FaultDisputeGame{FaultDisputeGameCaller: FaultDisputeGameCaller{contract: contract}, FaultDisputeGameTransactor: FaultDisputeGameTransactor{contract: contract}, FaultDisputeGameFilterer: FaultDisputeGameFilterer{contract: contract}}, nil -} - // FaultDisputeGame is an auto generated Go binding around an Ethereum contract. type FaultDisputeGame struct { FaultDisputeGameCaller // Read-only binding to the contract @@ -786,6 +764,68 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) L2BlockNumber() (*big.In return _FaultDisputeGame.Contract.L2BlockNumber(&_FaultDisputeGame.CallOpts) } +// L2BlockNumberChallenged is a free data retrieval call binding the contract method 0x3e3ac912. +// +// Solidity: function l2BlockNumberChallenged() view returns(bool) +func (_FaultDisputeGame *FaultDisputeGameCaller) L2BlockNumberChallenged(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _FaultDisputeGame.contract.Call(opts, &out, "l2BlockNumberChallenged") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// L2BlockNumberChallenged is a free data retrieval call binding the contract method 0x3e3ac912. +// +// Solidity: function l2BlockNumberChallenged() view returns(bool) +func (_FaultDisputeGame *FaultDisputeGameSession) L2BlockNumberChallenged() (bool, error) { + return _FaultDisputeGame.Contract.L2BlockNumberChallenged(&_FaultDisputeGame.CallOpts) +} + +// L2BlockNumberChallenged is a free data retrieval call binding the contract method 0x3e3ac912. +// +// Solidity: function l2BlockNumberChallenged() view returns(bool) +func (_FaultDisputeGame *FaultDisputeGameCallerSession) L2BlockNumberChallenged() (bool, error) { + return _FaultDisputeGame.Contract.L2BlockNumberChallenged(&_FaultDisputeGame.CallOpts) +} + +// L2BlockNumberChallenger is a free data retrieval call binding the contract method 0x30dbe570. +// +// Solidity: function l2BlockNumberChallenger() view returns(address) +func (_FaultDisputeGame *FaultDisputeGameCaller) L2BlockNumberChallenger(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _FaultDisputeGame.contract.Call(opts, &out, "l2BlockNumberChallenger") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// L2BlockNumberChallenger is a free data retrieval call binding the contract method 0x30dbe570. +// +// Solidity: function l2BlockNumberChallenger() view returns(address) +func (_FaultDisputeGame *FaultDisputeGameSession) L2BlockNumberChallenger() (common.Address, error) { + return _FaultDisputeGame.Contract.L2BlockNumberChallenger(&_FaultDisputeGame.CallOpts) +} + +// L2BlockNumberChallenger is a free data retrieval call binding the contract method 0x30dbe570. +// +// Solidity: function l2BlockNumberChallenger() view returns(address) +func (_FaultDisputeGame *FaultDisputeGameCallerSession) L2BlockNumberChallenger() (common.Address, error) { + return _FaultDisputeGame.Contract.L2BlockNumberChallenger(&_FaultDisputeGame.CallOpts) +} + // L2ChainId is a free data retrieval call binding the contract method 0xd6ae3cd5. // // Solidity: function l2ChainId() view returns(uint256 l2ChainId_) @@ -1341,25 +1381,46 @@ func (_FaultDisputeGame *FaultDisputeGameTransactorSession) AddLocalData(_ident return _FaultDisputeGame.Contract.AddLocalData(&_FaultDisputeGame.TransactOpts, _ident, _execLeafIdx, _partOffset) } -// Attack is a paid mutator transaction binding the contract method 0xc55cd0c7. +// Attack is a paid mutator transaction binding the contract method 0x472777c6. +// +// Solidity: function attack(bytes32 _disputed, uint256 _parentIndex, bytes32 _claim) payable returns() +func (_FaultDisputeGame *FaultDisputeGameTransactor) Attack(opts *bind.TransactOpts, _disputed [32]byte, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { + return _FaultDisputeGame.contract.Transact(opts, "attack", _disputed, _parentIndex, _claim) +} + +// Attack is a paid mutator transaction binding the contract method 0x472777c6. +// +// Solidity: function attack(bytes32 _disputed, uint256 _parentIndex, bytes32 _claim) payable returns() +func (_FaultDisputeGame *FaultDisputeGameSession) Attack(_disputed [32]byte, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { + return _FaultDisputeGame.Contract.Attack(&_FaultDisputeGame.TransactOpts, _disputed, _parentIndex, _claim) +} + +// Attack is a paid mutator transaction binding the contract method 0x472777c6. +// +// Solidity: function attack(bytes32 _disputed, uint256 _parentIndex, bytes32 _claim) payable returns() +func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Attack(_disputed [32]byte, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { + return _FaultDisputeGame.Contract.Attack(&_FaultDisputeGame.TransactOpts, _disputed, _parentIndex, _claim) +} + +// ChallengeRootL2Block is a paid mutator transaction binding the contract method 0x01935130. // -// Solidity: function attack(uint256 _parentIndex, bytes32 _claim) payable returns() -func (_FaultDisputeGame *FaultDisputeGameTransactor) Attack(opts *bind.TransactOpts, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { - return _FaultDisputeGame.contract.Transact(opts, "attack", _parentIndex, _claim) +// Solidity: function challengeRootL2Block((bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _headerRLP) returns() +func (_FaultDisputeGame *FaultDisputeGameTransactor) ChallengeRootL2Block(opts *bind.TransactOpts, _outputRootProof TypesOutputRootProof, _headerRLP []byte) (*types.Transaction, error) { + return _FaultDisputeGame.contract.Transact(opts, "challengeRootL2Block", _outputRootProof, _headerRLP) } -// Attack is a paid mutator transaction binding the contract method 0xc55cd0c7. +// ChallengeRootL2Block is a paid mutator transaction binding the contract method 0x01935130. // -// Solidity: function attack(uint256 _parentIndex, bytes32 _claim) payable returns() -func (_FaultDisputeGame *FaultDisputeGameSession) Attack(_parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { - return _FaultDisputeGame.Contract.Attack(&_FaultDisputeGame.TransactOpts, _parentIndex, _claim) +// Solidity: function challengeRootL2Block((bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _headerRLP) returns() +func (_FaultDisputeGame *FaultDisputeGameSession) ChallengeRootL2Block(_outputRootProof TypesOutputRootProof, _headerRLP []byte) (*types.Transaction, error) { + return _FaultDisputeGame.Contract.ChallengeRootL2Block(&_FaultDisputeGame.TransactOpts, _outputRootProof, _headerRLP) } -// Attack is a paid mutator transaction binding the contract method 0xc55cd0c7. +// ChallengeRootL2Block is a paid mutator transaction binding the contract method 0x01935130. // -// Solidity: function attack(uint256 _parentIndex, bytes32 _claim) payable returns() -func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Attack(_parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { - return _FaultDisputeGame.Contract.Attack(&_FaultDisputeGame.TransactOpts, _parentIndex, _claim) +// Solidity: function challengeRootL2Block((bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _headerRLP) returns() +func (_FaultDisputeGame *FaultDisputeGameTransactorSession) ChallengeRootL2Block(_outputRootProof TypesOutputRootProof, _headerRLP []byte) (*types.Transaction, error) { + return _FaultDisputeGame.Contract.ChallengeRootL2Block(&_FaultDisputeGame.TransactOpts, _outputRootProof, _headerRLP) } // ClaimCredit is a paid mutator transaction binding the contract method 0x60e27464. @@ -1383,25 +1444,25 @@ func (_FaultDisputeGame *FaultDisputeGameTransactorSession) ClaimCredit(_recipie return _FaultDisputeGame.Contract.ClaimCredit(&_FaultDisputeGame.TransactOpts, _recipient) } -// Defend is a paid mutator transaction binding the contract method 0x35fef567. +// Defend is a paid mutator transaction binding the contract method 0x7b0f0adc. // -// Solidity: function defend(uint256 _parentIndex, bytes32 _claim) payable returns() -func (_FaultDisputeGame *FaultDisputeGameTransactor) Defend(opts *bind.TransactOpts, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { - return _FaultDisputeGame.contract.Transact(opts, "defend", _parentIndex, _claim) +// Solidity: function defend(bytes32 _disputed, uint256 _parentIndex, bytes32 _claim) payable returns() +func (_FaultDisputeGame *FaultDisputeGameTransactor) Defend(opts *bind.TransactOpts, _disputed [32]byte, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { + return _FaultDisputeGame.contract.Transact(opts, "defend", _disputed, _parentIndex, _claim) } -// Defend is a paid mutator transaction binding the contract method 0x35fef567. +// Defend is a paid mutator transaction binding the contract method 0x7b0f0adc. // -// Solidity: function defend(uint256 _parentIndex, bytes32 _claim) payable returns() -func (_FaultDisputeGame *FaultDisputeGameSession) Defend(_parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { - return _FaultDisputeGame.Contract.Defend(&_FaultDisputeGame.TransactOpts, _parentIndex, _claim) +// Solidity: function defend(bytes32 _disputed, uint256 _parentIndex, bytes32 _claim) payable returns() +func (_FaultDisputeGame *FaultDisputeGameSession) Defend(_disputed [32]byte, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { + return _FaultDisputeGame.Contract.Defend(&_FaultDisputeGame.TransactOpts, _disputed, _parentIndex, _claim) } -// Defend is a paid mutator transaction binding the contract method 0x35fef567. +// Defend is a paid mutator transaction binding the contract method 0x7b0f0adc. // -// Solidity: function defend(uint256 _parentIndex, bytes32 _claim) payable returns() -func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Defend(_parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { - return _FaultDisputeGame.Contract.Defend(&_FaultDisputeGame.TransactOpts, _parentIndex, _claim) +// Solidity: function defend(bytes32 _disputed, uint256 _parentIndex, bytes32 _claim) payable returns() +func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Defend(_disputed [32]byte, _parentIndex *big.Int, _claim [32]byte) (*types.Transaction, error) { + return _FaultDisputeGame.Contract.Defend(&_FaultDisputeGame.TransactOpts, _disputed, _parentIndex, _claim) } // Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. @@ -1425,25 +1486,25 @@ func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Initialize() (*types return _FaultDisputeGame.Contract.Initialize(&_FaultDisputeGame.TransactOpts) } -// Move is a paid mutator transaction binding the contract method 0x632247ea. +// Move is a paid mutator transaction binding the contract method 0x6f034409. // -// Solidity: function move(uint256 _challengeIndex, bytes32 _claim, bool _isAttack) payable returns() -func (_FaultDisputeGame *FaultDisputeGameTransactor) Move(opts *bind.TransactOpts, _challengeIndex *big.Int, _claim [32]byte, _isAttack bool) (*types.Transaction, error) { - return _FaultDisputeGame.contract.Transact(opts, "move", _challengeIndex, _claim, _isAttack) +// Solidity: function move(bytes32 _disputed, uint256 _challengeIndex, bytes32 _claim, bool _isAttack) payable returns() +func (_FaultDisputeGame *FaultDisputeGameTransactor) Move(opts *bind.TransactOpts, _disputed [32]byte, _challengeIndex *big.Int, _claim [32]byte, _isAttack bool) (*types.Transaction, error) { + return _FaultDisputeGame.contract.Transact(opts, "move", _disputed, _challengeIndex, _claim, _isAttack) } -// Move is a paid mutator transaction binding the contract method 0x632247ea. +// Move is a paid mutator transaction binding the contract method 0x6f034409. // -// Solidity: function move(uint256 _challengeIndex, bytes32 _claim, bool _isAttack) payable returns() -func (_FaultDisputeGame *FaultDisputeGameSession) Move(_challengeIndex *big.Int, _claim [32]byte, _isAttack bool) (*types.Transaction, error) { - return _FaultDisputeGame.Contract.Move(&_FaultDisputeGame.TransactOpts, _challengeIndex, _claim, _isAttack) +// Solidity: function move(bytes32 _disputed, uint256 _challengeIndex, bytes32 _claim, bool _isAttack) payable returns() +func (_FaultDisputeGame *FaultDisputeGameSession) Move(_disputed [32]byte, _challengeIndex *big.Int, _claim [32]byte, _isAttack bool) (*types.Transaction, error) { + return _FaultDisputeGame.Contract.Move(&_FaultDisputeGame.TransactOpts, _disputed, _challengeIndex, _claim, _isAttack) } -// Move is a paid mutator transaction binding the contract method 0x632247ea. +// Move is a paid mutator transaction binding the contract method 0x6f034409. // -// Solidity: function move(uint256 _challengeIndex, bytes32 _claim, bool _isAttack) payable returns() -func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Move(_challengeIndex *big.Int, _claim [32]byte, _isAttack bool) (*types.Transaction, error) { - return _FaultDisputeGame.Contract.Move(&_FaultDisputeGame.TransactOpts, _challengeIndex, _claim, _isAttack) +// Solidity: function move(bytes32 _disputed, uint256 _challengeIndex, bytes32 _claim, bool _isAttack) payable returns() +func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Move(_disputed [32]byte, _challengeIndex *big.Int, _claim [32]byte, _isAttack bool) (*types.Transaction, error) { + return _FaultDisputeGame.Contract.Move(&_FaultDisputeGame.TransactOpts, _disputed, _challengeIndex, _claim, _isAttack) } // Resolve is a paid mutator transaction binding the contract method 0x2810e1d6. diff --git a/op-challenger/game/fault/contracts/faultdisputegame080.go b/op-challenger/game/fault/contracts/faultdisputegame080.go index cc30d21d7f941..eb7d707e3d71e 100644 --- a/op-challenger/game/fault/contracts/faultdisputegame080.go +++ b/op-challenger/game/fault/contracts/faultdisputegame080.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/sources/batching" "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" ) //go:embed abis/FaultDisputeGame-0.8.0.json diff --git a/op-e2e/e2eutils/disputegame/output_game_helper.go b/op-e2e/e2eutils/disputegame/output_game_helper.go index 124412e6cd019..d601ec48d593f 100644 --- a/op-e2e/e2eutils/disputegame/output_game_helper.go +++ b/op-e2e/e2eutils/disputegame/output_game_helper.go @@ -568,7 +568,7 @@ func (g *OutputGameHelper) Attack(ctx context.Context, claimIdx int64, claim com transactOpts := g.makeBondedTransactOpts(ctx, pos.Attack().ToGIndex(), cfg.Opts) err = g.sendMove(ctx, func() (*gethtypes.Transaction, error) { - return g.Game.Attack(transactOpts, big.NewInt(claimIdx), claim) + return g.Game.Attack(transactOpts, claimData.Claim, big.NewInt(claimIdx), claim) }) if err != nil { if cfg.ignoreDupes && g.hasClaim(ctx, claimIdx, attackPos, claim) { @@ -589,7 +589,7 @@ func (g *OutputGameHelper) Defend(ctx context.Context, claimIdx int64, claim com transactOpts := g.makeBondedTransactOpts(ctx, defendPos.ToGIndex(), cfg.Opts) err = g.sendMove(ctx, func() (*gethtypes.Transaction, error) { - return g.Game.Defend(transactOpts, big.NewInt(claimIdx), claim) + return g.Game.Defend(transactOpts, claimData.Claim, big.NewInt(claimIdx), claim) }) if err != nil { if cfg.ignoreDupes && g.hasClaim(ctx, claimIdx, defendPos, claim) {