From 8235f7713c0955f626e3ae4f9d2d857ae6c57532 Mon Sep 17 00:00:00 2001 From: billxu Date: Sun, 11 Aug 2024 16:33:21 +0800 Subject: [PATCH 1/3] Added an attack test with the da type as calldata. --- .../test/dispute/FaultDisputeGameN.t.sol | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/packages/contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol b/packages/contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol index a7a61e1a7fbe..e03b7d48b753 100644 --- a/packages/contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol +++ b/packages/contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol @@ -2199,6 +2199,57 @@ contract FaultDisputeGameN_Test is FaultDisputeGame_Init { bytes32 h = keccak256(abi.encode(_ident | (1 << 248), address(gameProxy), _localContext)); return bytes32((uint256(h) & ~uint256(0xFF << 248)) | (1 << 248)); } + + function test_stepAttackDummyClaim_attackDACalldata_succeeds() public { + // Give the test contract some ether + vm.deal(address(this), 1000 ether); + + bytes memory claimData1 = abi.encode(1, 1); + bytes memory claimData2 = abi.encode(2, 2); + bytes memory claimData3 = abi.encode(3, 3); + Claim claim1 = Claim.wrap(keccak256(claimData1)); + Claim claim2 = Claim.wrap(keccak256(claimData2)); + Claim claim3 = Claim.wrap(keccak256(claimData3)); + + bytes memory input = abi.encodePacked(claim1, claim2, claim3); // bytes.concat(claim1.raw(), claim2.raw(), claim3.raw()); + bytes memory claims = abi.encodePacked(claim1, claim2, claim3); + + // Make claims all the way down the tree. + (,,,, Claim disputed,,) = gameProxy.claimData(0); + gameProxy.attackV2{ value: _getRequiredBondV2(0, 0) }(disputed, 0, _dummyClaim(), 0); + + (,,,, disputed,,) = gameProxy.claimData(1); + gameProxy.attackV2{ value: _getRequiredBondV2(1, 0) }(disputed, 1, _dummyClaim(), 0); + + (,,,, disputed,,) = gameProxy.claimData(2); + gameProxy.attackV2{ value: _getRequiredBondV2(2, 0) }(disputed, 2, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC), 0); + + (,,,, disputed,,) = gameProxy.claimData(3); + uint256 bond = _getRequiredBondV2(3, 0); + gameProxy.attackV2{ value: bond }(disputed, 3, 0, LibDA.DA_TYPE_CALLDATA, claims); + vm.expectRevert(ClaimAlreadyExists.selector); + gameProxy.attackV2{ value: bond }(disputed, 3, Claim.wrap(LibDA.getClaimsHash(LibDA.DA_TYPE_CALLDATA, 3, input)), 0); + + + LibDA.DAItem memory preStateItem = LibDA.DAItem({ + daType: LibDA.DA_TYPE_CALLDATA, + dataHash: claim2.raw(), + proof: abi.encodePacked(claim1, claim3) + }); + LibDA.DAItem memory postStateItem = LibDA.DAItem({ + daType: LibDA.DA_TYPE_CALLDATA, + dataHash: claim3.raw(), + proof: bytes.concat(keccak256(abi.encode(claim1.raw(), claim2.raw()))) + }); + FaultDisputeGame.StepProof memory stepProof = FaultDisputeGame.StepProof({ + preStateItem: preStateItem, + postStateItem: postStateItem, + vmProof: hex"" + }); + + gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 4, 2, preStateItem); + gameProxy.stepV2({_claimIndex: 4, _attackBranch: 2, _stateData: claimData2, _proof: stepProof}); + } } contract FaultDisputeGameN_LessSplitDepth_Test is FaultDisputeGame_Init { From 6af98dfa2b270ce85a0718a734cf1c71afb3c927 Mon Sep 17 00:00:00 2001 From: billxu Date: Tue, 20 Aug 2024 09:25:46 +0800 Subject: [PATCH 2/3] Add comments and remove redundant code --- .../test/dispute/FaultDisputeGameN.t.sol | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol b/packages/contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol index e03b7d48b753..f86e18838c53 100644 --- a/packages/contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol +++ b/packages/contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol @@ -2211,7 +2211,6 @@ contract FaultDisputeGameN_Test is FaultDisputeGame_Init { Claim claim2 = Claim.wrap(keccak256(claimData2)); Claim claim3 = Claim.wrap(keccak256(claimData3)); - bytes memory input = abi.encodePacked(claim1, claim2, claim3); // bytes.concat(claim1.raw(), claim2.raw(), claim3.raw()); bytes memory claims = abi.encodePacked(claim1, claim2, claim3); // Make claims all the way down the tree. @@ -2228,8 +2227,15 @@ contract FaultDisputeGameN_Test is FaultDisputeGame_Init { uint256 bond = _getRequiredBondV2(3, 0); gameProxy.attackV2{ value: bond }(disputed, 3, 0, LibDA.DA_TYPE_CALLDATA, claims); vm.expectRevert(ClaimAlreadyExists.selector); - gameProxy.attackV2{ value: bond }(disputed, 3, Claim.wrap(LibDA.getClaimsHash(LibDA.DA_TYPE_CALLDATA, 3, input)), 0); + gameProxy.attackV2{ value: bond }(disputed, 3, Claim.wrap(LibDA.getClaimsHash(LibDA.DA_TYPE_CALLDATA, 3, claims)), 0); + // This variable is not used + LibDA.DAItem memory localDataItem = LibDA.DAItem({ + daType: LibDA.DA_TYPE_CALLDATA, + dataHash: '00000000000000000000000000000000', + proof: hex"" + }); + gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 4, 2, localDataItem); LibDA.DAItem memory preStateItem = LibDA.DAItem({ daType: LibDA.DA_TYPE_CALLDATA, @@ -2246,8 +2252,6 @@ contract FaultDisputeGameN_Test is FaultDisputeGame_Init { postStateItem: postStateItem, vmProof: hex"" }); - - gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 4, 2, preStateItem); gameProxy.stepV2({_claimIndex: 4, _attackBranch: 2, _stateData: claimData2, _proof: stepProof}); } } From c1d29c533a77d1540466bf317a4855d1bca4b9d4 Mon Sep 17 00:00:00 2001 From: billxu Date: Wed, 21 Aug 2024 10:34:32 +0800 Subject: [PATCH 3/3] Modify the variable definition in the unit test --- .../contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol b/packages/contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol index f86e18838c53..7cd7dfb7675f 100644 --- a/packages/contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol +++ b/packages/contracts-bedrock/test/dispute/FaultDisputeGameN.t.sol @@ -2229,13 +2229,12 @@ contract FaultDisputeGameN_Test is FaultDisputeGame_Init { vm.expectRevert(ClaimAlreadyExists.selector); gameProxy.attackV2{ value: bond }(disputed, 3, Claim.wrap(LibDA.getClaimsHash(LibDA.DA_TYPE_CALLDATA, 3, claims)), 0); - // This variable is not used - LibDA.DAItem memory localDataItem = LibDA.DAItem({ + LibDA.DAItem memory dummyDataItem = LibDA.DAItem({ daType: LibDA.DA_TYPE_CALLDATA, - dataHash: '00000000000000000000000000000000', + dataHash: _dummyClaim().raw(), proof: hex"" }); - gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 4, 2, localDataItem); + gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 4, 2, dummyDataItem); LibDA.DAItem memory preStateItem = LibDA.DAItem({ daType: LibDA.DA_TYPE_CALLDATA,