diff --git a/packages/contracts-bedrock/contracts/dispute/IAttestationDisputeGame.sol b/packages/contracts-bedrock/contracts/dispute/IAttestationDisputeGame.sol new file mode 100644 index 0000000000000000000000000000000000000000..4f28084ecba1dfe5498f0611edbf9ab146e10d61 --- /dev/null +++ b/packages/contracts-bedrock/contracts/dispute/IAttestationDisputeGame.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import { IDisputeGame } from "./IDisputeGame.sol"; + +/** + * @title IAttestationDisputeGame + * @notice The interface for an attestation-based DisputeGame meant to contest output + * proposals in Optimism's `L2OutputOracle` contract. + */ +interface IAttestationDisputeGame is IDisputeGame { + /** + * @notice A mapping of addresses from the `signerSet` to booleans signifying whether + * or not they have authorized the `rootClaim` to be invalidated. + * @param challenger The address to check for authorization. + * @return _challenged Whether or not the `challenger` has challenged the `rootClaim`. + */ + function challenges(address challenger) external view returns (bool _challenged); + + /** + * @notice The signer set consists of authorized public keys that may challenge + * the `rootClaim`. + * @param addr The address to check for authorization. + * @return _isAuthorized Whether or not the `addr` is part of the signer set. + */ + function signerSet(address addr) external view returns (bool _isAuthorized); + + /** + * @notice The amount of signatures required to successfully challenge the `rootClaim` + * output proposal. Once this threshold is met by members of the `signerSet` + * calling `challenge`, the game will be resolved to `CHALLENGER_WINS`. + * @custom:invariant The `signatureThreshold` may never be greater than the length + * of the `signerSet`. + * @return _signatureThreshold The amount of signatures required to successfully + * challenge the `rootClaim` output proposal. + */ + function frozenSignatureThreshold() external view returns (uint256 _signatureThreshold); + + /** + * @notice Returns the L2 Block Number that the `rootClaim` commits to. + * Exists within the `extraData`. + * @return _l2BlockNumber The L2 Block Number that the `rootClaim` commits to. + */ + function l2BlockNumber() external view returns (uint256 _l2BlockNumber); + + /** + * @notice Challenge the `rootClaim`. + * @dev - If the `ecrecover`ed address that created the signature is not a part of + * the signer set returned by `signerSet`, this function should revert. + * - If the `ecrecover`ed address that created the signature is not the + * msg.sender, this function should revert. + * - If the signature provided is the signature that breaches the signature + * threshold, the function should call the `resolve` function to resolve + * the game as `CHALLENGER_WINS`. + * - When the game resolves, the bond attached to the root claim should be + * distributed among the signers who participated in challenging the + * invalid claim. + * @param signature An EIP-712 signature committing to the `rootClaim` and + * `l2BlockNumber` (within the `extraData`) from a key that exists + * within the `signerSet`. + */ + function challenge(bytes calldata signature) external; +} diff --git a/packages/contracts-bedrock/contracts/dispute/IDisputeGameFactory.sol b/packages/contracts-bedrock/contracts/dispute/IDisputeGameFactory.sol new file mode 100644 index 0000000000000000000000000000000000000000..12eaa1e369a1804384b3bb776000e5774f669508 --- /dev/null +++ b/packages/contracts-bedrock/contracts/dispute/IDisputeGameFactory.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import { Claim, GameType } from "../libraries/DisputeTypes.sol"; + +import { IDisputeGame } from "./IDisputeGame.sol"; +import { IOwnable } from "./IOwnable.sol"; + +/** + * @title IDisputeGameFactory + * @notice The interface for a DisputeGameFactory contract. + */ +interface IDisputeGameFactory is IOwnable { + /** + * @notice Emitted when a new dispute game is created + * @param disputeProxy The address of the dispute game proxy + * @param gameType The type of the dispute game proxy's implementation + * @param rootClaim The root claim of the dispute game + */ + event DisputeGameCreated( + address indexed disputeProxy, + GameType indexed gameType, + Claim indexed rootClaim + ); + + /** + * @notice `games` queries an internal a mapping that maps the hash of + * `gameType ++ rootClaim ++ extraData` to the deployed `DisputeGame` clone. + * @dev `++` equates to concatenation. + * @param gameType The type of the DisputeGame - used to decide the proxy implementation + * @param rootClaim The root claim of the DisputeGame. + * @param extraData Any extra data that should be provided to the created dispute game. + * @return _proxy The clone of the `DisputeGame` created with the given parameters. + * Returns `address(0)` if nonexistent. + */ + function games( + GameType gameType, + Claim rootClaim, + bytes calldata extraData + ) external view returns (IDisputeGame _proxy); + + /** + * @notice `gameImpls` is a mapping that maps `GameType`s to their respective + * `IDisputeGame` implementations. + * @param gameType The type of the dispute game. + * @return _impl The address of the implementation of the game type. + * Will be cloned on creation of a new dispute game with the given `gameType`. + */ + function gameImpls(GameType gameType) external view returns (IDisputeGame _impl); + + /** + * @notice Creates a new DisputeGame proxy contract. + * @param gameType The type of the DisputeGame - used to decide the proxy implementation + * @param rootClaim The root claim of the DisputeGame. + * @param extraData Any extra data that should be provided to the created dispute game. + * @return proxy The address of the created DisputeGame proxy. + */ + function create( + GameType gameType, + Claim rootClaim, + bytes calldata extraData + ) external returns (IDisputeGame proxy); + + /** + * @notice Sets the implementation contract for a specific `GameType`. + * @dev May only be called by the `owner`. + * @param gameType The type of the DisputeGame. + * @param impl The implementation contract for the given `GameType`. + */ + function setImplementation(GameType gameType, IDisputeGame impl) external; +} diff --git a/packages/contracts-bedrock/contracts/dispute/IFaultDisputeGame.sol b/packages/contracts-bedrock/contracts/dispute/IFaultDisputeGame.sol new file mode 100644 index 0000000000000000000000000000000000000000..a1282a3faa052a95f5a892fa25227a8ae6987ac8 --- /dev/null +++ b/packages/contracts-bedrock/contracts/dispute/IFaultDisputeGame.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import { Claim, ClaimHash, Clock, Bond, Position, Timestamp } from "../libraries/DisputeTypes.sol"; + +import { IDisputeGame } from "./IDisputeGame.sol"; + +/** + * @title IFaultDisputeGame + * @notice The interface for a fault proof backed dispute game. + */ +interface IFaultDisputeGame is IDisputeGame { + /** + * @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 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); + + /** + * @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 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); + + /** + * @notice State variable of the starting timestamp of the game, set on deployment. + * @return The starting timestamp of the game + */ + function gameStart() external view returns (Timestamp); + + /** + * @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 (Bond 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 + */ + function attack(ClaimHash disagreement, Claim pivot) external; + + /** + * @notice Agree with a subclaim + * @param agreement The ClaimHash of the agreement + * @param pivot The claimed pivot + */ + function defend(ClaimHash agreement, Claim pivot) external; + + /** + * @notice Perform the final step via an on-chain fault proof processor + * @dev This function should point to a fault proof processor in order to execute + * a step in the fault proof program on-chain. The interface of the fault proof + * processor contract should be generic enough such that we can use different + * fault proof VMs (MIPS, RiscV5, etc.) + * @param disagreement The ClaimHash of the disagreement + */ + function step(ClaimHash disagreement) external; +} diff --git a/packages/contracts-bedrock/contracts/dispute/IOwnable.sol b/packages/contracts-bedrock/contracts/dispute/IOwnable.sol new file mode 100644 index 0000000000000000000000000000000000000000..d6dcd973215f98a8bc71e88c8fdcd16feb6c6c4e --- /dev/null +++ b/packages/contracts-bedrock/contracts/dispute/IOwnable.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +/** + * @title IOwnable + * @notice An interface for ownable contracts. + */ +interface IOwnable { + /** + * @notice Returns the owner of the contract + * @return _owner The address of the owner + */ + function owner() external view returns (address _owner); + + /** + * @notice Transfers ownership of the contract to a new address + * @dev May only be called by the contract owner + * @param newOwner The address to transfer ownership to + */ + function transferOwnership(address newOwner) external; +}