Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
507ddd2c
Commit
507ddd2c
authored
Jun 10, 2023
by
clabby
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Start simple bisection
parent
93a02de0
Changes
3
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
426 additions
and
228 deletions
+426
-228
FaultDisputeGame.sol
.../contracts-bedrock/contracts/dispute/FaultDisputeGame.sol
+185
-167
IFaultDisputeGame.sol
...edrock/contracts/dispute/interfaces/IFaultDisputeGame.sol
+26
-61
FaultDisputeGame.t.sol
...s/contracts-bedrock/contracts/test/FaultDisputeGame.t.sol
+215
-0
No files found.
packages/contracts-bedrock/contracts/dispute/FaultDisputeGame.sol
View file @
507ddd2c
This diff is collapsed.
Click to expand it.
packages/contracts-bedrock/contracts/dispute/interfaces/IFaultDisputeGame.sol
View file @
507ddd2c
...
...
@@ -10,86 +10,51 @@ import { IDisputeGame } from "./IDisputeGame.sol";
* @notice The interface for a fault proof backed dispute game.
*/
interface IFaultDisputeGame is IDisputeGame {
/**
* @notice The `ClaimData` struct represents the data associated with a Claim.
* @dev TODO: Pack `Clock` and `Position` into the same slot. Should require 4 64 bit arms.
* @dev TODO: Add bond ID information.
*/
struct ClaimData {
uint32 parentIndex;
uint32 rc;
bool countered;
Claim claim;
Position position;
Clock clock;
}
/**
* @notice Emitted when a subclaim is disagreed upon by `claimant`
* @dev Disagreeing with a subclaim is akin to attacking it.
* @param
claimHash The unique ClaimHash that is being disagreed upon
* @param
parentIndex The index within the `claimData` array of the parent claim
* @param pivot The claim for the following pivot (disagreement = go left)
* @param claimant The address of the claimant
*/
event Attack(
ClaimHash indexed claimHash
, Claim indexed pivot, address indexed claimant);
event Attack(
uint256 indexed parentIndex
, Claim indexed pivot, address indexed claimant);
/**
* @notice Emitted when a subclaim is agreed upon by `claimant`
* @dev Agreeing with a subclaim is akin to defending it.
* @param
claimHash The unique ClaimHash that is being agreed upon
* @param
parentIndex The index within the `claimData` array of the parent claim
* @param pivot The claim for the following pivot (agreement = go right)
* @param claimant The address of the claimant
*/
event Defend(
ClaimHash indexed claimHash
, Claim indexed pivot, address indexed claimant);
event Defend(
uint256 indexed parentIndex
, Claim indexed pivot, address indexed claimant);
/**
* @notice Maps a unique ClaimHash to a Claim.
* @param claimHash The unique ClaimHash
* @return claim The Claim associated with the ClaimHash
*/
function claims(ClaimHash claimHash) external view returns (Claim claim);
/**
* @notice Maps a unique ClaimHash to its parent.
* @param claimHash The unique ClaimHash
* @return parent The parent ClaimHash of the passed ClaimHash
*/
function parents(ClaimHash claimHash) external view returns (ClaimHash parent);
/**
* @notice Maps a unique ClaimHash to its Position.
* @param claimHash The unique ClaimHash
* @return position The Position associated with the ClaimHash
*/
function positions(ClaimHash claimHash) external view returns (Position position);
/**
* @notice Maps a unique ClaimHash to a Bond.
* @param claimHash The unique ClaimHash
* @return bond The Bond associated with the ClaimHash
*/
function bonds(ClaimHash claimHash) external view returns (BondAmount bond);
/**
* @notice Maps a unique ClaimHash its chess clock.
* @param claimHash The unique ClaimHash
* @return clock The chess clock associated with the ClaimHash
*/
function clocks(ClaimHash claimHash) external view returns (Clock clock);
/**
* @notice Maps a unique ClaimHash to its reference counter.
* @param claimHash The unique ClaimHash
* @return _rc The reference counter associated with the ClaimHash
*/
function rc(ClaimHash claimHash) external view returns (uint64 _rc);
/**
* @notice Maps a unique ClaimHash to a boolean indicating whether or not it has been countered.
* @param claimHash The unique claimHash
* @return _countered Whether or not `claimHash` has been countered
*/
function countered(ClaimHash claimHash) external view returns (bool _countered);
/**
* @notice Disagree with a subclaim
* @param disagreement The ClaimHash of the disagreement
* @param pivot The claimed pivot
* Attack a disagreed upon `Claim`.
* @param parentIndex Index of the `Claim` to attack in `claimData`.
* @param pivot The `Claim` at the relative attack position.
*/
function attack(
ClaimHash disagreement, Claim pivot) external
;
function attack(
uint256 parentIndex, Claim pivot) external payable
;
/**
*
@notice Agree with a subclaim
* @param
agreement The ClaimHash of the agreement
* @param pivot The
claimed pivot
*
Defend an agreed upon `Claim`.
* @param
parentIndex Index of the claim to defend in `claimData`.
* @param pivot The
`Claim` at the relative defense position.
*/
function defend(
ClaimHash agreement, Claim pivot) external
;
function defend(
uint256 parentIndex, Claim pivot) external payable
;
/**
* @notice Perform the final step via an on-chain fault proof processor
...
...
packages/contracts-bedrock/contracts/test/FaultDisputeGame.t.sol
0 → 100644
View file @
507ddd2c
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import { Test } from "forge-std/Test.sol";
import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol";
import { FaultDisputeGame } from "../dispute/FaultDisputeGame.sol";
import "../libraries/DisputeTypes.sol";
import { LibClock } from "../dispute/lib/LibClock.sol";
import { LibPosition } from "../dispute/lib/LibPosition.sol";
contract FaultDisputeGame_Test is Test {
/**
* @dev The root claim of the game.
*/
Claim internal constant ROOT_CLAIM = Claim.wrap(bytes32(uint256(10)));
/**
* @dev The extra data passed to the game for initialization.
*/
bytes internal constant EXTRA_DATA = abi.encode(1);
/**
* @dev The type of the game being tested.
*/
GameType internal constant GAME_TYPE = GameType.FAULT;
/**
* @dev The current version of the `FaultDisputeGame` contract.
*/
string internal constant VERSION = "0.0.1";
/**
* @dev The factory that will be used to create the game.
*/
DisputeGameFactory internal factory;
/**
* @dev The implementation of the game.
*/
FaultDisputeGame internal gameImpl;
/**
* @dev The `Clone` proxy of the game.
*/
FaultDisputeGame internal gameProxy;
function setUp() public {
// Deploy a new dispute game factory.
factory = new DisputeGameFactory(address(this));
// Deploy an implementation of the fault game
gameImpl = new FaultDisputeGame();
// Register the game implementation with the factory.
factory.setImplementation(GAME_TYPE, gameImpl);
// Create a new game.
gameProxy = FaultDisputeGame(address(factory.create(GAME_TYPE, ROOT_CLAIM, EXTRA_DATA)));
// Label the proxy
vm.label(address(gameProxy), "FaultDisputeGame_Clone");
}
////////////////////////////////////////////////////////////////
// `IDisputeGame` Implementation Tests //
////////////////////////////////////////////////////////////////
/**
* @dev Tests that the game's root claim is set correctly.
*/
function test_rootClaim_succeeds() public {
assertEq(Claim.unwrap(gameProxy.rootClaim()), Claim.unwrap(ROOT_CLAIM));
}
/**
* @dev Tests that the game's extra data is set correctly.
*/
function test_extraData_succeeds() public {
assertEq(gameProxy.extraData(), EXTRA_DATA);
}
/**
* @dev Tests that the game's version is set correctly.
*/
function test_version_succeeds() public {
assertEq(gameProxy.version(), VERSION);
}
/**
* @dev Tests that the game's status is set correctly.
*/
function test_gameStart_succeeds() public {
assertEq(Timestamp.unwrap(gameProxy.gameStart()), block.timestamp);
}
/**
* @dev Tests that the game's type is set correctly.
*/
function test_gameType_succeeds() public {
assertEq(uint256(gameProxy.gameType()), uint256(GAME_TYPE));
}
/**
* @dev Tests that the game's data is set correctly.
*/
function test_gameData_succeeds() public {
(GameType gameType, Claim rootClaim, bytes memory extraData) =
gameProxy.gameData();
assertEq(uint256(gameType), uint256(GAME_TYPE));
assertEq(Claim.unwrap(rootClaim), Claim.unwrap(ROOT_CLAIM));
assertEq(extraData, EXTRA_DATA);
}
////////////////////////////////////////////////////////////////
// `IFaultDisputeGame` Implementation Tests //
////////////////////////////////////////////////////////////////
/**
* @dev Tests that the root claim's data is set correctly when the game is initialized.
*/
function test_initialRootClaimData_succeeds() public {
(
uint32 parentIndex,
uint32 rc,
bool countered,
Claim claim,
Position position,
Clock clock
) = gameProxy.claimData(0);
assertEq(parentIndex, type(uint32).max);
assertEq(rc, 0);
assertEq(countered, false);
assertEq(Claim.unwrap(claim), Claim.unwrap(ROOT_CLAIM));
assertEq(Position.unwrap(position), 0);
assertEq(Clock.unwrap(clock), Clock.unwrap(LibClock.wrap(Duration.wrap(0), Timestamp.wrap(uint64(block.timestamp)))));
}
/**
* @dev Static unit test for the correctness of an opening attack.
*/
function test_simpleAttack_succeeds() public {
// Warp ahead 5 seconds.
vm.warp(block.timestamp + 5);
// Perform the attack.
gameProxy.attack(0, Claim.wrap(bytes32(uint(5))));
// Grab the claim data of the attack.
(
uint32 parentIndex,
uint32 rc,
bool countered,
Claim claim,
Position position,
Clock clock
) = gameProxy.claimData(1);
// Assert correctness of the attack claim's data.
assertEq(parentIndex, 0);
assertEq(rc, 0);
assertEq(countered, false);
assertEq(Claim.unwrap(claim), Claim.unwrap(Claim.wrap(bytes32(uint(5)))));
assertEq(Position.unwrap(position), Position.unwrap(LibPosition.attack(Position.wrap(0))));
assertEq(Clock.unwrap(clock), Clock.unwrap(LibClock.wrap(Duration.wrap(5), Timestamp.wrap(uint64(block.timestamp)))));
// Grab the claim data of the parent.
(
parentIndex,
rc,
countered,
claim,
position,
clock
) = gameProxy.claimData(0);
// Assert correctness of the parent claim's data.
assertEq(parentIndex, type(uint32).max);
assertEq(rc, 1);
assertEq(countered, true);
assertEq(Claim.unwrap(claim), Claim.unwrap(ROOT_CLAIM));
assertEq(Position.unwrap(position), 0);
assertEq(Clock.unwrap(clock), Clock.unwrap(LibClock.wrap(Duration.wrap(0), Timestamp.wrap(uint64(block.timestamp - 5)))));
// Resolve the game.
assertEq(uint256(gameProxy.resolve()), uint256(GameStatus.CHALLENGER_WINS));
}
}
/**
* @title BigStepper
* @notice A mock fault proof processor contract for testing purposes.
*⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
*⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⠶⢅⠒⢄⢔⣶⡦⣤⡤⠄⣀⠀⠀⠀⠀⠀⠀⠀
*⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠨⡏⠀⠀⠈⠢⣙⢯⣄⠀⢨⠯⡺⡘⢄⠀⠀⠀⠀⠀
*⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣶⡆⠀⠀⠀⠀⠈⠓⠬⡒⠡⣀⢙⡜⡀⠓⠄⠀⠀⠀
*⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡷⠿⣧⣀⡀⠀⠀⠀⠀⠀⠀⠉⠣⣞⠩⠥⠀⠼⢄⠀⠀
*⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⠀⠉⢹⣶⠒⠒⠂⠈⠉⠁⠘⡆⠀⣿⣿⠫⡄⠀
*⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⢶⣤⣀⡀⠀⠀⢸⡿⠀⠀⠀⠀⠀⢀⠞⠀⠀⢡⢨⢀⡄⠀
*⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡒⣿⢿⡤⠝⡣⠉⠁⠚⠛⠀⠤⠤⣄⡰⠁⠀⠀⠀⠉⠙⢸⠀⠀
*⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡤⢯⡌⡿⡇⠘⡷⠀⠁⠀⠀⢀⣰⠢⠲⠛⣈⣸⠦⠤⠶⠴⢬⣐⣊⡂⠀
*⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⡪⡗⢫⠞⠀⠆⣀⠻⠤⠴⠐⠚⣉⢀⠦⠂⠋⠁⠀⠁⠀⠀⠀⠀⢋⠉⠇⠀
*⠀⠀⠀⠀⣀⡤⠐⠒⠘⡹⠉⢸⠇⠸⠀⠀⠀⠀⣀⣤⠴⠚⠉⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⠀⣾⠀
*⠀⠀⠀⡰⠀⠉⠉⠀⠁⠀⠀⠈⢇⠈⠒⠒⠘⠈⢀⢡⡂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠀⢸⡄
*⠀⠀⠸⣿⣆⠤⢀⡀⠀⠀⠀⠀⢘⡌⠀⠀⣀⣀⣀⡈⣤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⢸⡇
*⠀⠀⢸⣀⠀⠉⠒⠐⠛⠋⠭⠭⠍⠉⠛⠒⠒⠒⠀⠒⠚⠛⠛⠛⠩⠭⠭⠭⠭⠤⠤⠤⠤⠤⠭⠭⠉⠓⡆
*⠀⠀⠘⠿⣷⣶⣤⣤⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇
*⠀⠀⠀⠀⠀⠉⠙⠛⠛⠻⠿⢿⣿⣿⣷⣶⣶⣶⣤⣤⣀⣁⣛⣃⣒⠿⠿⠿⠤⠠⠄⠤⠤⢤⣛⣓⣂⣻⡇
*⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠙⠛⠻⠿⠿⠿⢿⣿⣿⣿⣷⣶⣶⣾⣿⣿⣿⣿⠿⠟⠁
*⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀
*/
contract BigStepper {
/**
* @notice Steps from the `preState` to the `postState` by adding 1 to the `preState`.
* @param preState The pre state to start from
* @return postState The state stepped to
*/
function step(Claim preState) external pure returns (Claim postState) {
postState = Claim.wrap(bytes32(uint256(Claim.unwrap(preState)) + 1));
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment