-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: migrate OPSuccinctL2OutputOracle to OptimismPortalV2 (#277)
* forge install: solady v0.0.281 * feat: impl IDisputeGame for OPSuccinctL2OutputOracle * feat: update deployment * add a thin, clonable wrapper on OPSuccinctL2OutputOracle * add a test for OPSuccinctDisputeGame initialize() * use a more recent tx to make `testOPSuccinctDisputeGame` test pass * revert useless OPSuccinctL2OutputOracle IDisputeGame impl * add OPSuccinctDisputeGame bindings * add OPSuccinctDisputeGameFactory * allow to propose output roots using DisputeGameFactory * init deployment scripts * fix server in mock mode * use DGF if the address is provided * fmt * add deploy-dispute-game-factory to justfile * fix: don't disable logs on the server (#320) * feat: rc10 bump + fix mock mode (#323) * add test for OPSuccinctL2OutputOracleFactory * update book * small fixes * impl ISemver * set permissionless proposing in the deployment * OPSuccinctDisputeGameFactory: allow to change impl * proposer small fixes * don't pin op-deployer version for Kurtosis * forge fmt * update book * small fixes * nits * add a to do for GameTypes.OP_SUCCINCT
- Loading branch information
Showing
24 changed files
with
784 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Experimental | ||
|
||
This section contains experimental topics for OP Succinct. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# OptimismPortalV2 | ||
|
||
If you want to use `OptimismPortalV2` or conform to Optimism's `IDisputeGame`, you can follow this section that describe how to deploy the 2 contracts: | ||
|
||
* `OPSuccinctDisputeGame` a thin wrapper around `OPSuccinctL2OutputOracle` that implements `IDisputeGame`. | ||
* `OPSuccinctDisputeGameFactory` the proposer entry point when creating new dispute game. | ||
|
||
And instructions about how to configure the proposer to use them. | ||
|
||
After having done the step 2) either in mock or full mode, with `L2OO_ADDRESS` set with the address of the `OPSuccinctL2OutputOracle` contract in your `.env` file, | ||
run the following to deploy the contracts: | ||
|
||
```shell | ||
just deploy-dispute-game-factory | ||
``` | ||
|
||
If successful, you should see the following output: | ||
|
||
``` | ||
[⠊] Compiling... | ||
[⠊] Compiling 1 files with Solc 0.8.15 | ||
[⠒] Solc 0.8.15 finished in 1.93s | ||
Compiler run successful! | ||
Script ran successfully. | ||
== Return == | ||
0: address 0x6B3342821680031732Bc7d4E88A6528478aF9E38 | ||
## Setting up 1 EVM. | ||
========================== | ||
Chain 3151908 | ||
Estimated gas price: 1.000000014 gwei | ||
Estimated total gas used for script: 1614671 | ||
Estimated amount required: 0.001614671022605394 ETH | ||
========================== | ||
``` | ||
|
||
In these deployment logs, `0x6B3342821680031732Bc7d4E88A6528478aF9E38` is the address of the proxy for the `OPSuccinctDisputeGameFactory` contract. | ||
|
||
In order to have the poposer to use it, you have to add a new variable `DGF_ADDRESS` to your `.env` file with the value above. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"challenger": "0x0000000000000000000000000000000000000000", | ||
"finalizationPeriod": 3600, | ||
"l2BlockTime": 2, | ||
"owner": "0xDEd0000E32f8F40414d3ab3a830f735a3553E18e", | ||
"proposer": "0x0000000000000000000000000000000000000000", | ||
"rollupConfigHash": "0x0d7101e2acc7eae1fb42cfce5c604d14da561726e4e01b509315e5a9f97a9816", | ||
"startingBlockNumber": 5726082, | ||
"startingOutputRoot": "0xafcc854e9d3af302a5c749703bb4593fff9471f2ea1b55ec0ade1e1d3c4a0d6e", | ||
"startingTimestamp": 1733804652, | ||
"submissionInterval": 1200, | ||
"verifier": "0x397A5f7f3dBd538f23DE225B51f532c34448dA9B", | ||
"aggregationVkey": "0x00d4e72bc998d0528b0722a53bedd9c6f0143c9157af194ad4bb2502e37a496f", | ||
"rangeVkeyCommitment": "0x33e3678015df481724af3aac49d000923caeec277027610b1490f857769f9459" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.15; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
import {OPSuccinctL2OutputOracle} from "../src/OPSuccinctL2OutputOracle.sol"; | ||
import {OPSuccinctDisputeGame} from "../src/OPSuccinctDisputeGame.sol"; | ||
import {OPSuccinctDisputeGameFactory} from "../src/OPSuccinctDisputeGameFactory.sol"; | ||
import {Utils} from "../test/helpers/Utils.sol"; | ||
import {Proxy} from "@optimism/src/universal/Proxy.sol"; | ||
import {console} from "forge-std/console.sol"; | ||
|
||
contract OPSuccinctDFGDeployer is Script, Utils { | ||
function run() public returns (address) { | ||
vm.startBroadcast(); | ||
|
||
OPSuccinctL2OutputOracle l2OutputOracleProxy = OPSuccinctL2OutputOracle(vm.envAddress("L2OO_ADDRESS")); | ||
|
||
l2OutputOracleProxy.addProposer(address(0)); | ||
|
||
// Initialize the dispute game based on the existing L2OO_ADDRESS. | ||
OPSuccinctDisputeGame game = new OPSuccinctDisputeGame(address(l2OutputOracleProxy)); | ||
OPSuccinctDisputeGameFactory gameFactory = new OPSuccinctDisputeGameFactory(msg.sender, address(game)); | ||
|
||
vm.stopBroadcast(); | ||
|
||
return address(gameFactory); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.15; | ||
|
||
import {OPSuccinctL2OutputOracle} from "./OPSuccinctL2OutputOracle.sol"; | ||
import {CWIA} from "@solady/utils/legacy/CWIA.sol"; | ||
import {LibBytes} from "@solady/utils/LibBytes.sol"; | ||
import {ISemver} from "@optimism/src/universal/ISemver.sol"; | ||
import {IDisputeGame} from "@optimism/src/dispute/interfaces/IDisputeGame.sol"; | ||
import {Claim, GameStatus, GameType, GameTypes, Hash, Timestamp} from "@optimism/src/dispute/lib/Types.sol"; | ||
import {GameNotInProgress, OutOfOrderResolution} from "@optimism/src/dispute/lib/Errors.sol"; | ||
|
||
contract OPSuccinctDisputeGame is ISemver, CWIA, IDisputeGame { | ||
using LibBytes for bytes; | ||
|
||
/// @notice The address of the L2 output oracle proxy contract. | ||
address internal immutable l2OutpoutOracle; | ||
|
||
/// @notice The timestamp of the game's global creation. | ||
Timestamp public createdAt; | ||
|
||
/// @notice The timestamp of the game's global resolution. | ||
Timestamp public resolvedAt; | ||
|
||
/// @notice Returns the current status of the game. | ||
GameStatus public status; | ||
|
||
/// @notice Semantic version. | ||
/// @custom:semver v1.0.0-rc2 | ||
string public constant version = "v1.0.0-rc2"; | ||
|
||
constructor(address _l2OutpoutOracle) { | ||
l2OutpoutOracle = _l2OutpoutOracle; | ||
} | ||
|
||
//////////////////////////////////////////////////////////// | ||
// IDisputeGame impl // | ||
//////////////////////////////////////////////////////////// | ||
|
||
function initialize() external payable { | ||
createdAt = Timestamp.wrap(uint64(block.timestamp)); | ||
status = GameStatus.IN_PROGRESS; | ||
|
||
(uint256 l2BlockNumber, uint256 l1BlockNumber, bytes memory proof) = | ||
abi.decode(extraData(), (uint256, uint256, bytes)); | ||
|
||
OPSuccinctL2OutputOracle(l2OutpoutOracle).proposeL2Output( | ||
rootClaim().raw(), l2BlockNumber, l1BlockNumber, proof | ||
); | ||
|
||
this.resolve(); | ||
} | ||
|
||
/// @notice Getter for the game type. | ||
/// @dev The reference impl should be entirely different depending on the type (fault, validity) | ||
/// i.e. The game type should indicate the security model. | ||
/// @return gameType_ The type of proof system being used. | ||
function gameType() public pure returns (GameType) { | ||
// TODO: Once the following PR https://github.com/ethereum-optimism/optimism/pull/13780 is merged, | ||
// update this to return the correct game type: GameTypes.OP_SUCCINCT | ||
return GameType.wrap(3); | ||
} | ||
|
||
/// @notice Getter for the creator of the dispute game. | ||
/// @dev `clones-with-immutable-args` argument #1 | ||
/// @return The creator of the dispute game. | ||
function gameCreator() public pure returns (address) { | ||
return _getArgAddress(0x00); | ||
} | ||
|
||
/// @notice Getter for the root claim. | ||
/// @dev `clones-with-immutable-args` argument #2 | ||
/// @return The root claim of the DisputeGame. | ||
function rootClaim() public pure returns (Claim) { | ||
return Claim.wrap(_getArgBytes32(0x14)); | ||
} | ||
|
||
/// @notice Getter for the parent hash of the L1 block when the dispute game was created. | ||
/// @dev `clones-with-immutable-args` argument #3 | ||
/// @return The parent hash of the L1 block when the dispute game was created. | ||
function l1Head() public pure returns (Hash) { | ||
return Hash.wrap(_getArgBytes32(0x34)); | ||
} | ||
|
||
/// @notice Getter for the extra data. | ||
/// @dev `clones-with-immutable-args` argument #4 | ||
/// @return Any extra data supplied to the dispute game contract by the creator. | ||
function extraData() public pure returns (bytes memory) { | ||
// The extra data starts at the second word within the cwia calldata | ||
return _getArgBytes().slice(0x54); | ||
} | ||
|
||
/// @notice If all necessary information has been gathered, this function should mark the game | ||
/// status as either `CHALLENGER_WINS` or `DEFENDER_WINS` and return the status of | ||
/// the resolved game. It is at this stage that the bonds should be awarded to the | ||
/// necessary parties. | ||
/// @dev May only be called if the `status` is `IN_PROGRESS`. | ||
/// @return status_ The status of the game after resolution. | ||
function resolve() external returns (GameStatus status_) { | ||
// INVARIANT: Resolution cannot occur unless the game is currently in progress. | ||
if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); | ||
|
||
resolvedAt = Timestamp.wrap(uint64(block.timestamp)); | ||
status_ = GameStatus.DEFENDER_WINS; | ||
|
||
emit Resolved(status = status_); | ||
} | ||
|
||
/// @notice A compliant implementation of this interface should return the components of the | ||
/// game UUID's preimage provided in the cwia payload. The preimage of the UUID is | ||
/// constructed as `keccak256(gameType . rootClaim . extraData)` where `.` denotes | ||
/// concatenation. | ||
/// @return gameType_ The type of proof system being used. | ||
/// @return rootClaim_ The root claim of the DisputeGame. | ||
/// @return extraData_ Any extra data supplied to the dispute game contract by the creator. | ||
function gameData() external pure returns (GameType gameType_, Claim rootClaim_, bytes memory extraData_) { | ||
gameType_ = gameType(); | ||
rootClaim_ = rootClaim(); | ||
extraData_ = extraData(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.15; | ||
|
||
import {IDisputeGame} from "@optimism/src/dispute/interfaces/IDisputeGame.sol"; | ||
import {LibCWIA} from "@solady/utils/legacy/LibCWIA.sol"; | ||
import {ISemver} from "@optimism/src/universal/ISemver.sol"; | ||
|
||
contract OPSuccinctDisputeGameFactory is ISemver { | ||
using LibCWIA for address; | ||
|
||
/// @notice The owner of the contract, who has admin permissions. | ||
address public owner; | ||
|
||
/// @notice The address of the OP Succinct DisputeGame implementation contract. | ||
address public gameImpl; | ||
|
||
/// @notice Semantic version. | ||
/// @custom:semver v1.0.0-rc2 | ||
string public constant version = "v1.0.0-rc2"; | ||
|
||
//////////////////////////////////////////////////////////// | ||
// Modifiers // | ||
//////////////////////////////////////////////////////////// | ||
|
||
modifier onlyOwner() { | ||
require(msg.sender == owner, "OPSuccinctDisputeGameFactory: caller is not the owner"); | ||
_; | ||
} | ||
|
||
//////////////////////////////////////////////////////////// | ||
// Functions // | ||
//////////////////////////////////////////////////////////// | ||
|
||
/// @notice Constructs the OPSuccinctDisputeGameFactory contract. | ||
constructor(address _owner, address _gameImpl) { | ||
owner = _owner; | ||
gameImpl = _gameImpl; | ||
} | ||
|
||
/// @notice Creates a new DisputeGame proxy contract. | ||
function create(bytes32 _rootClaim, uint256 _l2BlockNumber, uint256 _l1BlockNumber, bytes memory _proof) | ||
external | ||
payable | ||
{ | ||
IDisputeGame game = IDisputeGame( | ||
gameImpl.clone( | ||
abi.encodePacked(msg.sender, _rootClaim, bytes32(0), abi.encode(_l2BlockNumber, _l1BlockNumber, _proof)) | ||
) | ||
); | ||
|
||
game.initialize{value: msg.value}(); | ||
} | ||
|
||
/// Updates the owner address. | ||
/// @param _owner The new owner address. | ||
function transferOwnership(address _owner) external onlyOwner { | ||
owner = _owner; | ||
} | ||
|
||
/// @notice Sets the implementation address. | ||
/// @param _implementation New implementation address. | ||
function setImplementation(address _implementation) external onlyOwner { | ||
gameImpl = _implementation; | ||
} | ||
} |
Oops, something went wrong.