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;
+}