Commit d5436b53 authored by clabby's avatar clabby Committed by GitHub

feat(ctb): Prevent duplicate `step` moves (#9653)

* Prevent duplicate steps

* Prevent duplicate step claims
parent e3235f46
This diff is collapsed.
...@@ -100,8 +100,8 @@ ...@@ -100,8 +100,8 @@
"sourceCodeHash": "0x1e5a6deded88804971fc1847c9eac65921771bff353437c0b29ed2f55513b984" "sourceCodeHash": "0x1e5a6deded88804971fc1847c9eac65921771bff353437c0b29ed2f55513b984"
}, },
"src/dispute/FaultDisputeGame.sol": { "src/dispute/FaultDisputeGame.sol": {
"initCodeHash": "0x44969c83852ed72e3152bcd98533fefa7b88116a939bf7ee4ad0f87dc9091ea2", "initCodeHash": "0xa06a5699121ff4b6f7bb89c43d56070fffee78c856363ead237e45ad6746db87",
"sourceCodeHash": "0x47a93c22df3b8481be0a553ba0ecccfc63cccf1ce7a5d908f11c940f4924b09a" "sourceCodeHash": "0x5f98e7357a45507c39366d3056a6c948d6be1a0b72a8758c66396041aa823fc9"
}, },
"src/legacy/DeployerWhitelist.sol": { "src/legacy/DeployerWhitelist.sol": {
"initCodeHash": "0x8de80fb23b26dd9d849f6328e56ea7c173cd9e9ce1f05c9beea559d1720deb3d", "initCodeHash": "0x8de80fb23b26dd9d849f6328e56ea7c173cd9e9ce1f05c9beea559d1720deb3d",
......
...@@ -623,6 +623,11 @@ ...@@ -623,6 +623,11 @@
"name": "ClockTimeExceeded", "name": "ClockTimeExceeded",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "DuplicateStep",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "GameDepthExceeded", "name": "GameDepthExceeded",
......
...@@ -638,6 +638,11 @@ ...@@ -638,6 +638,11 @@
"name": "ClockTimeExceeded", "name": "ClockTimeExceeded",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "DuplicateStep",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "GameDepthExceeded", "name": "GameDepthExceeded",
......
...@@ -81,8 +81,8 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { ...@@ -81,8 +81,8 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver {
bool internal initialized; bool internal initialized;
/// @notice Semantic version. /// @notice Semantic version.
/// @custom:semver 0.5.0 /// @custom:semver 0.6.0
string public constant version = "0.5.0"; string public constant version = "0.6.0";
/// @param _gameType The type ID of the game. /// @param _gameType The type ID of the game.
/// @param _absolutePrestate The absolute prestate of the instruction trace. /// @param _absolutePrestate The absolute prestate of the instruction trace.
...@@ -193,6 +193,9 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { ...@@ -193,6 +193,9 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver {
bool parentPostAgree = (parentPos.depth() - postState.position.depth()) % 2 == 0; bool parentPostAgree = (parentPos.depth() - postState.position.depth()) % 2 == 0;
if (parentPostAgree == validStep) revert ValidStep(); if (parentPostAgree == validStep) revert ValidStep();
// INVARIANT: A step cannot be made against a claim for a second time.
if (parent.counteredBy != address(0)) revert DuplicateStep();
// Set the parent claim as countered. We do not need to append a new claim to the game; // Set the parent claim as countered. We do not need to append a new claim to the game;
// instead, we can just set the existing parent as countered. // instead, we can just set the existing parent as countered.
parent.counteredBy = msg.sender; parent.counteredBy = msg.sender;
......
...@@ -88,6 +88,10 @@ error ClaimAboveSplit(); ...@@ -88,6 +88,10 @@ error ClaimAboveSplit();
/// depth of the game. /// depth of the game.
error InvalidSplitDepth(); error InvalidSplitDepth();
/// @notice Thrown when trying to step against a claim for a second time, after it has already been countered with
/// an instruction step.
error DuplicateStep();
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// `PermissionedDisputeGame` Errors // // `PermissionedDisputeGame` Errors //
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
......
...@@ -442,6 +442,27 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -442,6 +442,27 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
gameProxy.attack{ value: 0 }(0, _dummyClaim()); gameProxy.attack{ value: 0 }(0, _dummyClaim());
} }
/// @dev Tests that a claim cannot be stepped against twice.
function test_step_duplicateStep_reverts() public {
// Give the test contract some ether
vm.deal(address(this), 100 ether);
// Make claims all the way down the tree.
gameProxy.attack{ value: 1 ether }(0, _dummyClaim());
gameProxy.attack{ value: 1 ether }(1, _dummyClaim());
gameProxy.attack{ value: 1 ether }(2, _dummyClaim());
gameProxy.attack{ value: 1 ether }(3, _dummyClaim());
gameProxy.attack{ value: 1 ether }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC));
gameProxy.attack{ value: 1 ether }(5, _dummyClaim());
gameProxy.attack{ value: 1 ether }(6, _dummyClaim());
gameProxy.attack{ value: 1 ether }(7, _dummyClaim());
gameProxy.addLocalData(LocalPreimageKey.STARTING_L2_BLOCK_NUMBER, 8, 0);
gameProxy.step(8, true, absolutePrestateData, hex"");
vm.expectRevert(DuplicateStep.selector);
gameProxy.step(8, true, absolutePrestateData, hex"");
}
/// @dev Static unit test for the correctness an uncontested root resolution. /// @dev Static unit test for the correctness an uncontested root resolution.
function test_resolve_rootUncontested_succeeds() public { function test_resolve_rootUncontested_succeeds() public {
vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment