Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add zk fault proof contracts #258

Open
wants to merge 16 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@
[submodule "packages/contracts-bedrock/lib/automate"]
path = packages/contracts-bedrock/lib/automate
url = https://github.com/gelatodigital/automate
[submodule "packages/contracts-bedrock/lib/sp1-contracts"]
path = packages/contracts-bedrock/lib/sp1-contracts
url = https://github.com/lightning-li/sp1-contracts
7 changes: 6 additions & 1 deletion packages/contracts-bedrock/deploy-config/hardhat.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,10 @@
"daChallengeWindow": 100,
"daResolveWindow": 100,
"daBondSize": 1000,
"daResolverRefundPercentage": 50
"daResolverRefundPercentage": 50,
"blockDistance": 3,
"aggregationVkey": "0x0006a81df67f2d5e48048edd5c051a5be0ef9720a2ce130f12f7021256160e73",
"rangeVkeyCommitment": "0x5030974a2d74c494158e4af45836d72e2e0acae55f0f22d73c22bde90c1d6d98",
"sp1VerifierGateway": "0x51d3960c929B27Db3f041eA3c3aD4fF3c2A121C7",
"rollupConfigHash": "0x0b9b35ba1f4265979a10dea49f5501f81b3729b2856165574b1661323678e778"
}
36 changes: 36 additions & 0 deletions packages/contracts-bedrock/deployments/97-deploy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"AddressManager": "0x2e234DAe75C793f67A35089C9d99245E1C58470b",
"AnchorStateRegistry": "0x03D97F75CF5cE8986dc4fF531047AF2D52631aBE",
"AnchorStateRegistryProxy": "0x1aF7f588A501EA2B5bB3feeFA744892aA2CF00e6",
"DelayedWETH": "0x7dB36fC81A5197f84BDc88C9B1237A0fca492Cf4",
"DelayedWETHProxy": "0x756e0562323ADcDA4430d6cb456d9151f605290B",
"DisputeGameFactory": "0xc1B724FAe275423BE62006d7711b4435C31a3Fa2",
"DisputeGameFactoryProxy": "0xDB25A7b768311dE128BBDa7B8426c3f9C74f3240",
"L1CrossDomainMessenger": "0x9c0A33f6b1c5d574a6327101c597b0e792a4DC05",
"L1CrossDomainMessengerProxy": "0xD16d567549A2a2a2005aEACf7fB193851603dd70",
"L1ERC721Bridge": "0xF9A2bc3F5DA471245c57da74cfCF6Cdf5fb8040F",
"L1ERC721BridgeProxy": "0x13aa49bAc059d709dd0a18D6bb63290076a702D7",
"L1StandardBridge": "0x7ad421ef511CB1D0060fC90BBccCcf5735632f74",
"L1StandardBridgeProxy": "0x3D7Ebc40AF7092E3F1C81F2e996cbA5Cae2090d7",
"L2OutputOracle": "0x451CEA9b04c58DBC5770c1b1455a67440111b35f",
"L2OutputOracleProxy": "0x3381cD18e2Fb4dB236BF0525938AB6E43Db0440f",
"Mips": "0x71Fb6e45FA9D2396ffc32cd8605141d1af7ab957",
"OptimismMintableERC20Factory": "0x13E136063f4699eBf276c66125f8eA02adaB4F77",
"OptimismMintableERC20FactoryProxy": "0x96d3F6c20EEd2697647F543fE6C08bC2Fbf39758",
"OptimismPortal": "0x1fF359e524EB80A26D1D63D580B223f53120c65B",
"OptimismPortal2": "0x956486516159D5fDfAC9ee63759676A033A5bC88",
"OptimismPortalProxy": "0x212224D2F2d262cd093eE13240ca4873fcCBbA3C",
"PreimageOracle": "0x194C0E304fCA9281698112f40438bcb0D9F82544",
"ProtocolVersions": "0x3cea74C40CB33ae630e130516097cDd0cd06Cb5E",
"ProtocolVersionsProxy": "0x03A6a84cD762D9707A21605b548aaaB891562aAb",
"ProxyAdmin": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a",
"SafeProxyFactory": "0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2",
"SafeSingleton": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552",
"SuperchainConfig": "0x9Fd48Cb6F987Cc0CbEC82A870C51Ec54cA16e599",
"SuperchainConfigProxy": "0xa0Cb889707d426A7A386870A03bc70d1b0697598",
"SystemConfig": "0xcC02cfD0D02e17d2805485f6878aFeE5da00A028",
"SystemConfigProxy": "0x2a07706473244BC757E10F2a9E86fB532828afe3",
"SystemOwnerSafe": "0xf82F7e298c13195A73c702625D49a1BD739cFaaF",
"ZkFaultProofConfig": "0xD384139842Cfff55fB7dC930e782cc09139a1cEe",
"ZkFaultProofConfigProxy": "0xe8dc788818033232EF9772CB2e6622F1Ec8bc840"
}
1 change: 1 addition & 0 deletions packages/contracts-bedrock/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ remappings = [
'@rari-capital/solmate/=lib/solmate',
'@lib-keccak/=lib/lib-keccak/contracts/lib',
'@solady/=lib/solady/src',
"@sp1-contracts/=lib/sp1-contracts/contracts/",
'forge-std/=lib/forge-std/src',
'ds-test/=lib/forge-std/lib/ds-test/src',
'safe-contracts/=lib/safe-contracts/contracts',
Expand Down
1 change: 1 addition & 0 deletions packages/contracts-bedrock/lib/sp1-contracts
Submodule sp1-contracts added at 25b159
66 changes: 65 additions & 1 deletion packages/contracts-bedrock/scripts/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol";
import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol";
import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol";
import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol";
import { ZkFaultProofConfig } from "src/dispute/ZkFaultProofConfig.sol";
import { PreimageOracle } from "src/cannon/PreimageOracle.sol";
import { MIPS } from "src/cannon/MIPS.sol";
import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol";
Expand All @@ -58,6 +59,9 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
import { ForgeArtifacts } from "scripts/ForgeArtifacts.sol";
import { Process } from "scripts/libraries/Process.sol";

import { SP1VerifierGateway } from "sp1-contracts/src/SP1VerifierGateway.sol";
import { SP1Verifier } from "sp1-contracts/src/v3.0.0-rc4/SP1VerifierPlonk.sol";

/// @title Deploy
/// @notice Script used to deploy a bedrock system. The entire system is deployed within the `run` function.
/// To add a new contract to the system, add a public function that deploys that individual contract.
Expand Down Expand Up @@ -152,6 +156,7 @@ contract Deploy is Deployer {
DisputeGameFactory: mustGetAddress("DisputeGameFactoryProxy"),
DelayedWETH: mustGetAddress("DelayedWETHProxy"),
AnchorStateRegistry: mustGetAddress("AnchorStateRegistryProxy"),
ZkFaultProofConfig: mustGetAddress("ZkFaultProofConfigProxy"),
OptimismMintableERC20Factory: mustGetAddress("OptimismMintableERC20FactoryProxy"),
OptimismPortal: mustGetAddress("OptimismPortalProxy"),
OptimismPortal2: mustGetAddress("OptimismPortalProxy"),
Expand All @@ -171,6 +176,7 @@ contract Deploy is Deployer {
DisputeGameFactory: getAddress("DisputeGameFactoryProxy"),
DelayedWETH: getAddress("DelayedWETHProxy"),
AnchorStateRegistry: getAddress("AnchorStateRegistryProxy"),
ZkFaultProofConfig: getAddress("ZkFaultProofConfigProxy"),
OptimismMintableERC20Factory: getAddress("OptimismMintableERC20FactoryProxy"),
OptimismPortal: getAddress("OptimismPortalProxy"),
OptimismPortal2: getAddress("OptimismPortalProxy"),
Expand Down Expand Up @@ -370,6 +376,7 @@ contract Deploy is Deployer {
deployERC1967Proxy("L2OutputOracleProxy");
deployERC1967Proxy("DelayedWETHProxy");
deployERC1967Proxy("AnchorStateRegistryProxy");
deployERC1967Proxy("ZkFaultProofConfigProxy");

transferAddressManagerOwnership(); // to the ProxyAdmin
}
Expand All @@ -392,6 +399,8 @@ contract Deploy is Deployer {
deployPreimageOracle();
deployMips();
deployAnchorStateRegistry();
deployZkFaultProofConfig();
deploySp1VerifierSuite();
}

/// @notice Initialize all of the implementations
Expand All @@ -415,6 +424,7 @@ contract Deploy is Deployer {
initializeDisputeGameFactory();
initializeDelayedWETH();
initializeAnchorStateRegistry();
initializeZkFaultProofConfig();
}

/// @notice Add Plasma setup to the OP chain
Expand Down Expand Up @@ -813,6 +823,29 @@ contract Deploy is Deployer {
addr_ = address(anchorStateRegistry);
}

function deployZkFaultProofConfig() public broadcast returns (address addr_) {
console.log("Deploying ZkFaultProofConfig implementation");
ZkFaultProofConfig config = new ZkFaultProofConfig{ salt: _implSalt() }();
save("ZkFaultProofConfig", address(config));
console.log("ZkFaultProofConfig deployed at %s", address(config));

addr_ = address(config);
}

function deploySp1VerifierSuite() public broadcast returns (address addr_) {
console.log("Deploying SP1VerifierGateway implementation");
SP1VerifierGateway suite = new SP1VerifierGateway();
save("SP1VerifierGateway", address(suite));
console.log("SP1VerifierGateway deployed at %s", address(suite));


addr_ = address(suite);
console.log("Deploying PlonkVerifier implementation");

address verifier = address(new SP1Verifier());
suite.addRoute(verifier);
}

/// @notice Deploy the SystemConfig
function deploySystemConfig() public broadcast returns (address addr_) {
console.log("Deploying SystemConfig implementation");
Expand Down Expand Up @@ -957,7 +990,7 @@ contract Deploy is Deployer {
address anchorStateRegistryProxy = mustGetAddress("AnchorStateRegistryProxy");
address anchorStateRegistry = mustGetAddress("AnchorStateRegistry");

AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](5);
AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](6);
roots[0] = AnchorStateRegistry.StartingAnchorRoot({
gameType: GameTypes.CANNON,
outputRoot: OutputRoot({
Expand Down Expand Up @@ -987,6 +1020,13 @@ contract Deploy is Deployer {
})
});
roots[4] = AnchorStateRegistry.StartingAnchorRoot({
gameType: GameTypes.ZKFAULT,
outputRoot: OutputRoot({
root: Hash.wrap(cfg.faultGameGenesisOutputRoot()),
l2BlockNumber: cfg.faultGameGenesisBlock()
})
});
roots[5] = AnchorStateRegistry.StartingAnchorRoot({
gameType: GameTypes.FAST,
outputRoot: OutputRoot({
root: Hash.wrap(cfg.faultGameGenesisOutputRoot()),
Expand All @@ -1004,6 +1044,30 @@ contract Deploy is Deployer {
console.log("AnchorStateRegistry version: %s", version);
}

function initializeZkFaultProofConfig() public broadcast {
console.log("Upgrading and initializing ZkFaultProofConfig proxy");
address zkFaultProofConfigProxy = mustGetAddress("ZkFaultProofConfigProxy");
address zkFaultProofConfig = mustGetAddress("ZkFaultProofConfig");
address sp1VerifierGateway = mustGetAddress("SP1VerifierGateway");

_upgradeAndCallViaSafe({
_proxy: payable(zkFaultProofConfigProxy),
_implementation: zkFaultProofConfig,
_innerCallData: abi.encodeCall(ZkFaultProofConfig.initialize, (
cfg.finalSystemOwner(),
cfg.blockDistance(),
cfg.l2ChainID(),
cfg.aggregationVkey(),
cfg.rangeVkeyCommitment(),
sp1VerifierGateway,
cfg.rollupConfigHash()
))
});

string memory version = ZkFaultProofConfig(payable(zkFaultProofConfigProxy)).version();
console.log("ZkFaultProofConfig version: %s", version);
}

/// @notice Initialize the SystemConfig
function initializeSystemConfig() public broadcast {
console.log("Upgrading and initializing SystemConfig proxy");
Expand Down
11 changes: 11 additions & 0 deletions packages/contracts-bedrock/scripts/DeployConfig.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ contract DeployConfig is Script {
uint256 public daResolveWindow;
uint256 public daBondSize;
uint256 public daResolverRefundPercentage;
uint256 public blockDistance;
bytes32 public aggregationVkey;
bytes32 public rangeVkeyCommitment;
address public sp1VerifierGateway;
bytes32 public rollupConfigHash;

bool public useCustomGasToken;
address public customGasTokenAddress;
Expand Down Expand Up @@ -155,6 +160,12 @@ contract DeployConfig is Script {
daBondSize = _readOr(_json, "$.daBondSize", 1000000000);
daResolverRefundPercentage = _readOr(_json, "$.daResolverRefundPercentage", 0);

blockDistance = stdJson.readUint(_json, "$.blockDistance");
aggregationVkey = stdJson.readBytes32(_json, "$.aggregationVkey");
rangeVkeyCommitment = stdJson.readBytes32(_json, "$.rangeVkeyCommitment");
sp1VerifierGateway = stdJson.readAddress(_json, "$.sp1VerifierGateway");
rollupConfigHash = stdJson.readBytes32(_json, "$.rollupConfigHash");

useCustomGasToken = _readOr(_json, "$.useCustomGasToken", false);
customGasTokenAddress = _readOr(_json, "$.customGasTokenAddress", address(0));

Expand Down
1 change: 1 addition & 0 deletions packages/contracts-bedrock/scripts/Types.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ library Types {
address DisputeGameFactory;
address DelayedWETH;
address AnchorStateRegistry;
address ZkFaultProofConfig;
address OptimismMintableERC20Factory;
address OptimismPortal;
address OptimismPortal2;
Expand Down
101 changes: 100 additions & 1 deletion packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,110 @@
emit DisputeGameCreated(address(proxy_), _gameType, _rootClaim);
}

function _prepareExtraData(
uint256 l2BlockNumber,
Claim[] memory claims,
address parentProxy,
bytes memory extraData
) private pure returns (bytes memory) {
// calculate the hash of all _claims
bytes32 claimsHash = keccak256(abi.encodePacked(claims));
return abi.encodePacked(
l2BlockNumber,
claimsHash,
uint32(claims.length),
parentProxy,
extraData
);
}

function _validateGameCreation(
GameType _gameType,
Claim[] calldata _claims,
uint64 _parentGameIndex,
IDisputeGame impl
) private view returns (IDisputeGame parentProxy) {
// If there is no implementation to clone for the given `GameType`, revert.
if (address(impl) == address(0)) revert NoImplementation(_gameType);
// If the required initialization bond is not met, revert.
if (msg.value != initBonds[_gameType]) revert IncorrectBondAmount();
if (_claims.length == 0) revert NoClaims();
// When the parent game index is the maximum value of a uint64, it means that there is no parent game.
// And use the state from anchor state registry.
if (_parentGameIndex != type(uint64).max && _parentGameIndex >= _disputeGameList.length) {
revert InvalidParentGameIndex();
}
if (_parentGameIndex != type(uint64).max) {
(GameType parentGameType, , address proxy) = _disputeGameList[_parentGameIndex].unpack();
parentProxy = IDisputeGame(proxy);
// The parent game must be of the same type as the child game.
if (parentGameType.raw() != _gameType.raw()) revert InvalidParentGameType();
if (parentProxy.status() == GameStatus.CHALLENGER_WINS) {
revert InvalidParentGameStatus();
}
} else {
parentProxy = IDisputeGame(address(0));
}
}
Comment on lines +151 to +178

function createZkFaultDisputeGame(
GameType _gameType,
Claim[] calldata _claims,
uint64 _parentGameIndex,
uint64 _l2BlockNumber,
bytes calldata _extraData
) external
payable
returns (IDisputeGame proxy_)
{
// Grab the implementation contract for the given `GameType`.
IDisputeGame impl = gameImpls[_gameType];
IDisputeGame parentProxy = _validateGameCreation(_gameType, _claims, _parentGameIndex, impl);
// Clone the implementation contract and initialize it with the given parameters.
//
// CWIA Calldata Layout:
// ┌───────────────────────────┬────────────────────────────────────┐
// │ Bytes │ Description │
// ├───────────────────────────┼────────────────────────────────────┤
// │ [0, 20) │ Game creator address │
// | [20, 52) | Root claim |
// │ [52, 84) │ Parent block hash at creation time │
// │ [84, 84+n) │ Extra data │
// | [84, 116) | L2 block number |
// | [116, 148) | Hash of all claims |
// | [148, 152) | The length of claims |
// | [152, 172) | Parent game address |
// └───────────────────────────┴────────────────────────────────────┘
Claim rootClaim = _claims[_claims.length-1];
bytes memory extraData = _prepareExtraData(
_l2BlockNumber,
_claims,
address(parentProxy),
_extraData
);
proxy_ = IDisputeGame(address(impl).clone(abi.encodePacked(msg.sender, rootClaim, blockhash(block.number - 1), extraData)));
proxy_.initialize{ value: msg.value }();

// Compute the unique identifier for the dispute game.
Hash uuid = getGameUUID(_gameType, rootClaim, extraData);
// If a dispute game with the same UUID already exists, revert.
if (GameId.unwrap(_disputeGames[uuid]) != bytes32(0)) revert GameAlreadyExists(uuid);

// Pack the game ID.
GameId id = LibGameId.pack(_gameType, Timestamp.wrap(uint64(block.timestamp)), address(proxy_));

// Store the dispute game id in the mapping & emit the `DisputeGameCreated` event.
_disputeGames[uuid] = id;
_disputeGameList.push(id);
emit DisputeGameCreated(address(proxy_), _gameType, rootClaim);
emit ZkDisputeGameIndexUpdated(_disputeGameList.length - 1);

}
Fixed Show fixed Hide fixed
/// @inheritdoc IDisputeGameFactory
function getGameUUID(
GameType _gameType,
Claim _rootClaim,
bytes calldata _extraData
bytes memory _extraData
)
public
pure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver {
numRemainingChildren_ = challengeIndicesLen - checkpoint.subgameIndex;
}

/// @inheritdoc IFaultDisputeGame
/// @inheritdoc IDisputeGame
function l2BlockNumber() public pure returns (uint256 l2BlockNumber_) {
l2BlockNumber_ = _getArgUint256(0x54);
}
Expand Down
Loading
Loading