Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 3 additions & 1 deletion deploy-config/sepolia.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,7 @@
"multiproofGenesisBlockNumber": 37223829,
"multiproofBlockInterval": 100,
"multiproofIntermediateBlockInterval": 10,
"multiproofProofThreshold": 1
"multiproofProofThreshold": 1,
"risc0VerifierRouter": "0xb121b667dd2cf27f95f9f5107137696f56f188f6",
"risc0SetBuilderImageId": "0x70909b25db0db00f1d4b4016aeb876f53568a3e5a8e6397cb562d79947a02cc9"
}
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ remappings = [
'@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts',
'@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts',
'@openzeppelin/contracts-v5/=lib/openzeppelin-contracts-v5/contracts',
'openzeppelin/=lib/risc0-ethereum/lib/openzeppelin-contracts/',
'@rari-capital/solmate/=lib/solmate',
'@lib-keccak/=lib/lib-keccak/contracts/lib',
'solady/=lib/solady/src/',
Expand Down
17 changes: 16 additions & 1 deletion scripts/deploy/DeployConfig.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ contract DeployConfig is Script {
uint256 public multiproofIntermediateBlockInterval;
uint256 public multiproofProofThreshold;

// RISC Zero / NitroEnclaveVerifier Configuration (reference values; DeployRiscZeroStack takes these as CLI args)
bytes32 public risc0SetBuilderImageId;
bytes32 public nitroRootCert;
bytes32 public nitroVerifierId;
bytes32 public nitroVerifierProofId;
address public nitroProofSubmitter;
address public risc0VerifierRouter;

bool public useInterop;
bool public useUpgradedFork;
bytes32 public devFeatureBitmap;
Expand Down Expand Up @@ -208,12 +216,19 @@ contract DeployConfig is Script {
multiproofConfigHash = bytes32(_readOr(_json, "$.multiproofConfigHash", 0));
multiproofGameType = _readOr(_json, "$.multiproofGameType", 621);
teeProposer = _readOr(_json, "$.teeProposer", finalSystemOwner);
nitroEnclaveVerifier = stdJson.readAddress(_json, "$.nitroEnclaveVerifier");
nitroEnclaveVerifier = _readOr(_json, "$.nitroEnclaveVerifier", address(0));
multiproofGenesisOutputRoot = bytes32(_readOr(_json, "$.multiproofGenesisOutputRoot", uint256(1)));
multiproofGenesisBlockNumber = _readOr(_json, "$.multiproofGenesisBlockNumber", 0);
multiproofBlockInterval = _readOr(_json, "$.multiproofBlockInterval", 100);
multiproofIntermediateBlockInterval = _readOr(_json, "$.multiproofIntermediateBlockInterval", 10);
multiproofProofThreshold = _readOr(_json, "$.multiproofProofThreshold", 1);

risc0SetBuilderImageId = bytes32(_readOr(_json, "$.risc0SetBuilderImageId", 0));
nitroRootCert = bytes32(_readOr(_json, "$.nitroRootCert", 0));
nitroVerifierId = bytes32(_readOr(_json, "$.nitroVerifierId", 0));
nitroVerifierProofId = bytes32(_readOr(_json, "$.nitroVerifierProofId", 0));
nitroProofSubmitter = _readOr(_json, "$.nitroProofSubmitter", address(0));
risc0VerifierRouter = _readOr(_json, "$.risc0VerifierRouter", address(0));
}

function fork() public view returns (Fork fork_) {
Expand Down
138 changes: 41 additions & 97 deletions scripts/multiproof/DeployDevWithNitro.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,42 +12,19 @@ pragma solidity 0.8.15;
* This script deploys infrastructure using the REAL TEEProverRegistry, which
* REQUIRES a ZK proof of a valid AWS Nitro attestation for signer registration.
* You cannot use addDevSigner() - you must go through the full registerSigner() flow.
* A pre-deployed NitroEnclaveVerifier contract address must be provided in the config.
*
* USE THIS SCRIPT WHEN:
* - Testing the full Nitro attestation flow end-to-end
* - You have access to a real AWS Nitro enclave
* - You want to validate the production registration process
*
* DO NOT USE THIS SCRIPT IF:
* - You don't have a Nitro enclave available
* - You just want quick local testing (use DeployDevNoNitro instead)
*
* NOTE: This still uses mocks for AnchorStateRegistry, DelayedWETH, and ZK Verifier,
* so it's not a full production deployment - just production-like for the
* Nitro attestation flow.
*
* ─────────────────────────────────────────────────────────────────────────────────
* STEP 1: Register the PCR0 (enclave image hash) - OWNER ONLY
* ─────────────────────────────────────────────────────────────────────────────────
*
* The PCR0 is the raw 48-byte hash of the enclave image. You must register it
* before any signers using that image can be registered.
*
* # Get raw PCR0 bytes from the enclave (48 bytes, hex-encoded)
* PCR0_RAW="0x<48_bytes_hex>"
*
* # Register it (only owner can do this)
* cast send $TEE_PROVER_REGISTRY "registerPCR0(bytes)" $PCR0_RAW \
* --private-key $OWNER_KEY --rpc-url $RPC_URL
*
* Note: The teeImageHash in deploy-config is keccak256(PCR0_RAW), not the raw bytes.
* PREREQUISITES:
* 1. Deploy the RISC Zero verifier stack AND NitroEnclaveVerifier using
* DeployRiscZeroStack.s.sol (required because NitroEnclaveVerifier and its
* dependencies need Solidity ^0.8.20, while this script is pinned to =0.8.15).
* 2. Set `nitroEnclaveVerifier` in the deploy config to the deployed address.
*
* ─────────────────────────────────────────────────────────────────────────────────
* STEP 2: Generate ZK proof of the attestation and register the signer
* SIGNER REGISTRATION FLOW
* ─────────────────────────────────────────────────────────────────────────────────
*
* Generate a Risc0 ZK proof of the Nitro attestation offchain, then call:
* After deployment, register a signer by generating a RISC Zero ZK proof of a
* valid AWS Nitro attestation document and calling:
*
* cast send $TEE_PROVER_REGISTRY \
* "registerSigner(bytes,bytes)" $ZK_OUTPUT $ZK_PROOF_BYTES \
Expand All @@ -56,33 +33,6 @@ pragma solidity 0.8.15;
* IMPORTANT: The attestation is only valid for 60 minutes! Generate the proof
* and submit the transaction within that window.
*
* ─────────────────────────────────────────────────────────────────────────────────
* VERIFICATION
* ─────────────────────────────────────────────────────────────────────────────────
*
* After registration, verify the signer is registered:
*
* # Check if signer is valid
* cast call $TEE_PROVER_REGISTRY "isValidSigner(address)(bool)" $SIGNER_ADDRESS
*
* # Check if the signer is registered
* cast call $TEE_PROVER_REGISTRY "isValidSigner(address)(bool)" $SIGNER_ADDRESS
*
* ─────────────────────────────────────────────────────────────────────────────────
* COMPARISON WITH DeployDevNoNitro
* ─────────────────────────────────────────────────────────────────────────────────
*
* | Feature | DeployDevNoNitro | DeployDevWithNitro |
* |----------------------------|------------------------|------------------------|
* | TEEProverRegistry | DevTEEProverRegistry | TEEProverRegistry |
* | Signer registration | addDevSigner() | registerSigner() |
* | Requires Nitro enclave | No | Yes |
* | Validates attestation (ZK) | No | Yes |
* | PCR0 pre-registration | No | Yes |
* | Attestation freshness | N/A | < 60 minutes |
*
* Both scripts use mocks for AnchorStateRegistry, DelayedWETH, and ZK Verifier.
*
* ══════════════════════════════════════════════════════════════════════════════════
*/

Expand Down Expand Up @@ -114,6 +64,7 @@ import { MockDelayedWETH } from "./mocks/MockDelayedWETH.sol";
/// @title DeployDevWithNitro
/// @notice Development deployment WITH AWS Nitro attestation validation.
/// @dev Uses real TEEProverRegistry which requires registerSigner() with valid attestation.
/// NitroEnclaveVerifier must be pre-deployed via DeployRiscZeroStack.s.sol.
contract DeployDevWithNitro is Script {
/// @notice Constant from Optimism's Constants.sol - the storage slot for proxy admin.
bytes32 internal constant PROXY_OWNER_ADDRESS = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
Expand All @@ -127,6 +78,7 @@ contract DeployDevWithNitro is Script {
DeployConfig(address(uint160(uint256(keccak256(abi.encode("optimism.deployconfig"))))));

// Deployed addresses
address public nitroEnclaveVerifierAddr;
address public teeProverRegistryProxy;
address public teeVerifier;
address public disputeGameFactory;
Expand All @@ -142,19 +94,26 @@ contract DeployDevWithNitro is Script {
function run() public {
GameType gameType = GameType.wrap(uint32(cfg.multiproofGameType()));

// NitroEnclaveVerifier must be pre-deployed (via DeployRiscZeroStack.s.sol)
nitroEnclaveVerifierAddr = cfg.nitroEnclaveVerifier();
require(
nitroEnclaveVerifierAddr != address(0),
"nitroEnclaveVerifier must be set in config (deploy via DeployRiscZeroStack.s.sol first)"
);

console.log("=== Deploying Dev Infrastructure (WITH NITRO) ===");
console.log("Chain ID:", block.chainid);
console.log("Owner:", cfg.finalSystemOwner());
console.log("TEE Proposer:", cfg.teeProposer());
console.log("Game Type:", cfg.multiproofGameType());
console.log("NitroEnclaveVerifier:", nitroEnclaveVerifierAddr);
console.log("");
console.log("NOTE: Using REAL TEEProverRegistry - ZK attestation proof REQUIRED.");
console.log("NitroEnclaveVerifier:", cfg.nitroEnclaveVerifier());

vm.startBroadcast();

_deployInfrastructure(gameType);
_deployTEEContracts(cfg.finalSystemOwner(), cfg.nitroEnclaveVerifier());
_deployTEEContracts(cfg.finalSystemOwner());
_deployAggregateVerifier(gameType);

vm.stopBroadcast();
Expand All @@ -163,11 +122,12 @@ contract DeployDevWithNitro is Script {
_writeOutput();
}

function _deployTEEContracts(address owner, address _nitroEnclaveVerifier) internal {
function _deployTEEContracts(address owner) internal {
address scgImpl = address(
new TEEProverRegistry(INitroEnclaveVerifier(_nitroEnclaveVerifier), IDisputeGameFactory(disputeGameFactory))
new TEEProverRegistry(
INitroEnclaveVerifier(nitroEnclaveVerifierAddr), IDisputeGameFactory(disputeGameFactory)
)
);
console.log("NitroEnclaveVerifier (external):", _nitroEnclaveVerifier);
teeProverRegistryProxy = address(
new TransparentUpgradeableProxy(
scgImpl,
Expand All @@ -186,11 +146,6 @@ contract DeployDevWithNitro is Script {
console.log("TEEVerifier:", teeVerifier);
}

function _registerProposer(address teeProposer) internal {
TEEProverRegistry(teeProverRegistryProxy).setProposer(teeProposer, true);
console.log("Registered TEE proposer:", teeProposer);
}

function _deployInfrastructure(GameType gameType) internal {
address factoryImpl = address(new DisputeGameFactory());
MinimalProxyAdmin proxyAdmin = new MinimalProxyAdmin(cfg.finalSystemOwner());
Expand Down Expand Up @@ -249,7 +204,7 @@ contract DeployDevWithNitro is Script {
console.log(" DEV DEPLOYMENT COMPLETE (WITH NITRO)");
console.log("========================================");
console.log("\nTEE Contracts:");
console.log(" NitroEnclaveVerifier (external):", cfg.nitroEnclaveVerifier());
console.log(" NitroEnclaveVerifier:", nitroEnclaveVerifierAddr);
console.log(" TEEProverRegistry:", teeProverRegistryProxy);
console.log(" TEEVerifier:", teeVerifier);
console.log("\nInfrastructure:");
Expand All @@ -262,38 +217,27 @@ contract DeployDevWithNitro is Script {
console.log(" TEE Image Hash:", vm.toString(cfg.teeImageHash()));
console.log(" Config Hash:", vm.toString(cfg.multiproofConfigHash()));
console.log("========================================");
console.log("\n>>> NEXT STEPS (ZK ATTESTATION PROOF REQUIRED) <<<");
console.log("\n1. Register the PCR0 (raw 48-byte enclave image hash):");
console.log(" cast send", teeProverRegistryProxy);
console.log(' "registerPCR0(bytes)" <PCR0_RAW_BYTES>');
console.log(" --private-key <OWNER_KEY> --rpc-url <RPC>");
console.log("\n2. Generate a Risc0 ZK proof of the Nitro attestation offchain.");
console.log("\n3. Register signer with ZK proof:");
console.log(" cast send", teeProverRegistryProxy);
console.log(' "registerSigner(bytes,bytes)" <ZK_OUTPUT> <ZK_PROOF_BYTES>');
console.log(" --private-key <OWNER_OR_MANAGER_KEY> --rpc-url <RPC>");
console.log("\nSee the comments at the top of this file for full details.");
console.log("========================================\n");
console.log("\n>>> NEXT STEP: Register signer with ZK attestation proof <<<");
console.log("\n cast send", teeProverRegistryProxy);
console.log(' "registerSigner(bytes,bytes)" <ZK_OUTPUT> <ZK_PROOF_BYTES>');
console.log(" --private-key <OWNER_OR_MANAGER_KEY> --rpc-url <RPC>");
console.log("\n========================================\n");
}

function _writeOutput() internal {
// Build the JSON output with all deployed addresses
string memory json = "";
json = string.concat(json, '{"TEEProverRegistry":"', vm.toString(teeProverRegistryProxy));
json = string.concat(json, '","TEEVerifier":"', vm.toString(teeVerifier));
json = string.concat(json, '","NitroEnclaveVerifier":"', vm.toString(nitroEnclaveVerifierAddr));
json = string.concat(json, '","DisputeGameFactory":"', vm.toString(disputeGameFactory));
json = string.concat(json, '","AnchorStateRegistry":"', vm.toString(mockAnchorRegistry));
json = string.concat(json, '","DelayedWETH":"', vm.toString(mockDelayedWETH));
json = string.concat(json, '","AggregateVerifier":"', vm.toString(aggregateVerifier));
json = string.concat(json, '"}');

string memory outPath = string.concat("deployments/", vm.toString(block.chainid), "-dev-with-nitro.json");
string memory output = string.concat(
'{"TEEProverRegistry":"',
vm.toString(teeProverRegistryProxy),
'","TEEVerifier":"',
vm.toString(teeVerifier),
'","DisputeGameFactory":"',
vm.toString(disputeGameFactory),
'","AnchorStateRegistry":"',
vm.toString(mockAnchorRegistry),
'","DelayedWETH":"',
vm.toString(mockDelayedWETH),
'","AggregateVerifier":"',
vm.toString(aggregateVerifier),
'"}'
);
vm.writeFile(outPath, output);
vm.writeFile(outPath, json);
console.log("Deployment saved to:", outPath);
}
}
Loading
Loading