From 97c6af10a7142b9de32780225c786b6c63d3e1ce Mon Sep 17 00:00:00 2001 From: Mihir Wadekar Date: Wed, 20 May 2026 17:25:37 -0700 Subject: [PATCH 1/4] feat: add zk and tee hash upgrade template Add a reusable setup template for redeploying AggregateVerifier with updated verifier hashes and wiring the multisig approval flow. Co-authored-by: Cursor --- .github/workflows/validate-templates.yml | 4 + Makefile | 8 + README.md | 17 +- .../template-upgrade-zk-and-tee-hash/.env | 22 +++ .../FACILITATOR.md | 116 ++++++++++++ .../template-upgrade-zk-and-tee-hash/Makefile | 79 ++++++++ .../README.md | 65 +++++++ .../foundry.toml | 36 ++++ .../script/DeployAggregateVerifier.s.sol | 144 +++++++++++++++ .../script/UpdateVerifierHashes.s.sol | 170 ++++++++++++++++++ 10 files changed, 660 insertions(+), 1 deletion(-) create mode 100644 setup-templates/template-upgrade-zk-and-tee-hash/.env create mode 100644 setup-templates/template-upgrade-zk-and-tee-hash/FACILITATOR.md create mode 100644 setup-templates/template-upgrade-zk-and-tee-hash/Makefile create mode 100644 setup-templates/template-upgrade-zk-and-tee-hash/README.md create mode 100644 setup-templates/template-upgrade-zk-and-tee-hash/foundry.toml create mode 100644 setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol create mode 100644 setup-templates/template-upgrade-zk-and-tee-hash/script/UpdateVerifierHashes.s.sol diff --git a/.github/workflows/validate-templates.yml b/.github/workflows/validate-templates.yml index 4b74f85a..9cd1b25d 100644 --- a/.github/workflows/validate-templates.yml +++ b/.github/workflows/validate-templates.yml @@ -40,6 +40,10 @@ jobs: setup_target: "setup-upgrade-fault-proofs" setup_args: "network=sepolia" task_dir_suffix: upgrade-fault-proofs + - template: template-upgrade-zk-and-tee-hash + setup_target: "setup-upgrade-zk-and-tee-hash" + setup_args: "network=sepolia" + task_dir_suffix: upgrade-zk-and-tee-hash - template: template-pause-bridge-base setup_target: "setup-bridge-pause" setup_args: "network=sepolia" diff --git a/Makefile b/Makefile index 40437f2c..0538450d 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ PROJECT_DIR = $(network)/$(shell date +'%Y-%m-%d')-$(task) GAS_INCREASE_DIR = $(network)/$(shell date +'%Y-%m-%d')-increase-gas-limit GAS_AND_ELASTICITY_INCREASE_DIR = $(network)/$(shell date +'%Y-%m-%d')-increase-gas-and-elasticity-limit FAULT_PROOF_UPGRADE_DIR = $(network)/$(shell date +'%Y-%m-%d')-upgrade-fault-proofs +ZK_AND_TEE_HASH_UPGRADE_DIR = $(network)/$(shell date +'%Y-%m-%d')-upgrade-zk-and-tee-hash SAFE_MANAGEMENT_DIR = $(network)/$(shell date +'%Y-%m-%d')-safe-management FUNDING_DIR = $(network)/$(shell date +'%Y-%m-%d')-funding SET_BASE_BRIDGE_PARTNER_THRESHOLD_DIR = $(network)/$(shell date +'%Y-%m-%d')-pause-bridge-base @@ -19,6 +20,7 @@ TEMPLATE_GENERIC = setup-templates/template-generic TEMPLATE_GAS_INCREASE = setup-templates/template-gas-increase TEMPLATE_GAS_AND_ELASTICITY_INCREASE = setup-templates/template-gas-and-elasticity-increase TEMPLATE_UPGRADE_FAULT_PROOFS = setup-templates/template-upgrade-fault-proofs +TEMPLATE_UPGRADE_ZK_AND_TEE_HASH = setup-templates/template-upgrade-zk-and-tee-hash TEMPLATE_SAFE_MANAGEMENT = setup-templates/template-safe-management TEMPLATE_FUNDING = setup-templates/template-funding TEMPLATE_SET_BASE_BRIDGE_PARTNER_THRESHOLD = setup-templates/template-set-bridge-partner-threshold @@ -99,6 +101,12 @@ setup-upgrade-fault-proofs: cp -r $(TEMPLATE_UPGRADE_FAULT_PROOFS) $(FAULT_PROOF_UPGRADE_DIR) mkdir -p $(network)/signatures/$(notdir $(FAULT_PROOF_UPGRADE_DIR)) +# Run `make setup-upgrade-zk-and-tee-hash network=` +setup-upgrade-zk-and-tee-hash: + rm -rf $(TEMPLATE_UPGRADE_ZK_AND_TEE_HASH)/cache $(TEMPLATE_UPGRADE_ZK_AND_TEE_HASH)/lib $(TEMPLATE_UPGRADE_ZK_AND_TEE_HASH)/out + cp -r $(TEMPLATE_UPGRADE_ZK_AND_TEE_HASH) $(ZK_AND_TEE_HASH_UPGRADE_DIR) + mkdir -p $(network)/signatures/$(notdir $(ZK_AND_TEE_HASH_UPGRADE_DIR)) + # Run `make setup-safe-management network=` setup-safe-management: rm -rf $(TEMPLATE_SAFE_MANAGEMENT)/cache $(TEMPLATE_SAFE_MANAGEMENT)/lib $(TEMPLATE_SAFE_MANAGEMENT)/out diff --git a/README.md b/README.md index 96d5de0c..5f3fbc2a 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ To execute a new task, run one of the following commands (depending on the type - For gas increase tasks: `make setup-gas-increase network=` - For combined gas, elasticity, and DA footprint gas scalar tasks: `make setup-gas-and-elasticity-increase network=` - For fault proof upgrade: `make setup-upgrade-fault-proofs network=` +- For upgrading multiproof ZK and TEE hashes: `make setup-upgrade-zk-and-tee-hash network=` - For safe management tasks: `make setup-safe-management network=` - For funding tasks: `make setup-funding network=` - For updating the partner threshold in Base Bridge: `make setup-bridge-partner-threshold network=` @@ -117,7 +118,7 @@ Each task will have a directory structure similar to the following: ## CI — Template Validation -A GitHub Actions workflow automatically validates all 10 setup-templates on every pull request and on pushes to `main`. +A GitHub Actions workflow automatically validates all 11 setup-templates on every pull request and on pushes to `main`. **What CI checks for each template:** @@ -269,6 +270,20 @@ This template is used to upgrade the fault proof contracts. This is commonly don 1. Check in the task when it's ready to sign and collect signatures from signers 1. Once executed, check in the records files and mark the task `EXECUTED` in the README. +## Using the ZK and TEE hash upgrade template + +This template is used to redeploy a multiproof `AggregateVerifier` with new `TEE_IMAGE_HASH`, `ZK_RANGE_HASH`, and `ZK_AGGREGATE_HASH` values, then update `DisputeGameFactory.gameImpls(gameType)` to point at the new verifier. + +1. Ensure you have followed the instructions above in `setup`. +1. Run `make setup-upgrade-zk-and-tee-hash network=` and go to the folder that was created by this command. +1. Specify the commit of [Base contracts code](https://github.com/base/contracts) you intend to use in the `.env` file. +1. Set `GAME_TYPE`, `TEE_IMAGE_HASH`, `ZK_RANGE_HASH`, `ZK_AGGREGATE_HASH`, `PROXY_ADMIN_OWNER`, and `DISPUTE_GAME_FACTORY_PROXY` in the task's `.env` file. +1. Run `make deps` and `forge build`. +1. Deploy the replacement verifier with `make deploy-aggregate-verifier VERIFIER_API_KEY=...`; this writes `addresses.json`. +1. Generate signer validations with `make gen-validation-update-verifier-hashes-cb` and `make gen-validation-update-verifier-hashes-sc`. +1. Check in the task when it's ready to sign and request facilitators to collect signatures from signers. +1. Once executed, check in the records files and mark the task `EXECUTED` in the README. + ## Using the safe management template This template is used to perform ownership management on a Gnosis Safe, like the incident multisig, specifically it can be used to change the owners of the multisig. diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/.env b/setup-templates/template-upgrade-zk-and-tee-hash/.env new file mode 100644 index 00000000..56a91865 --- /dev/null +++ b/setup-templates/template-upgrade-zk-and-tee-hash/.env @@ -0,0 +1,22 @@ +# Required: Git commit hash for https://github.com/base/contracts +BASE_CONTRACTS_COMMIT=1baa168c9db6a946ae47863ea07295bedb3599a6 + +# Network-specific addresses are automatically loaded from {network}/.env via include ../.env. + +# Multiproof configuration. +# The scripts use DISPUTE_GAME_FACTORY_PROXY + GAME_TYPE as the source of truth +# to recover the live AggregateVerifier and its current immutables. +GAME_TYPE= + +# Verifier deployment inputs. +TEE_IMAGE_HASH= +ZK_RANGE_HASH= +ZK_AGGREGATE_HASH= + +# Re-exported for task simulation UI. The signer-tool invokes forge directly and +# does not pick up variables coming from the Makefile's include ../.env. +PROXY_ADMIN_OWNER= +DISPUTE_GAME_FACTORY_PROXY= + +# Validation generation +RECORD_STATE_DIFF=true diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/FACILITATOR.md b/setup-templates/template-upgrade-zk-and-tee-hash/FACILITATOR.md new file mode 100644 index 00000000..745c8e7f --- /dev/null +++ b/setup-templates/template-upgrade-zk-and-tee-hash/FACILITATOR.md @@ -0,0 +1,116 @@ +# Facilitator Guide + +Guide for facilitators managing this task. + +## Deployment prerequisites + +Before collecting signatures, complete the EOA-authorized phase: + +```bash +cd contract-deployments +git pull +cd /-upgrade-zk-and-tee-hash +make deps +make deploy-aggregate-verifier VERIFIER_API_KEY=... +``` + +`make deploy-aggregate-verifier` runs `DeployAggregateVerifier`: + +- redeploys `AggregateVerifier` with the same immutables as the existing one, overriding `TEE_IMAGE_HASH`, `ZK_RANGE_HASH`, and `ZK_AGGREGATE_HASH` +- reuses the existing `ZkVerifier` from the current on-chain AggregateVerifier +- writes `aggregateVerifier` to `addresses.json` + +Expected `addresses.json` keys: + +- `aggregateVerifier` + +## Task origin signing + +After setting up the task, generate cryptographic attestations to prove who created and facilitated the task. These signatures are stored in `/signatures//`. + +### Task creator + +```bash +make sign-as-task-creator +``` + +### Base facilitator + +```bash +make sign-as-base-facilitator +``` + +### Security Council facilitator + +```bash +make sign-as-sc-facilitator +``` + +## Generate validation files + +```bash +cd contract-deployments +git pull +cd /-upgrade-zk-and-tee-hash +make deps +make gen-validation-update-verifier-hashes-cb +make gen-validation-update-verifier-hashes-sc +``` + +This produces: + +- `validations/base-signer.json` +- `validations/base-signer-2.json` + +## Execute the transaction + +### 1. Update repo + +```bash +cd contract-deployments +git pull +cd /-upgrade-zk-and-tee-hash +make deps +``` + +### 2. Collect signatures for `CB_MULTISIG` + +Concatenate all signatures and export as the `SIGNATURES` environment variable: + +```bash +export SIGNATURES="[SIGNATURE1][SIGNATURE2]..." +``` + +Then run: + +```bash +SIGNATURES=$SIGNATURES make approve-update-verifier-hashes-cb +``` + +### 3. Collect signatures for `BASE_SECURITY_COUNCIL` + +Concatenate all signatures and export as the `SIGNATURES` environment variable: + +```bash +export SIGNATURES="[SIGNATURE1][SIGNATURE2]..." +``` + +Then run: + +```bash +SIGNATURES=$SIGNATURES make approve-update-verifier-hashes-sc +``` + +### 4. Execute upgrade batch + +```bash +make execute-update-verifier-hashes +``` + +Post-checks enforced by script: + +- `DisputeGameFactory.gameImpls(gameType)` equals the newly deployed `aggregateVerifier` +- `aggregateVerifier.TEE_IMAGE_HASH()` equals the configured `TEE_IMAGE_HASH` +- `aggregateVerifier.ZK_RANGE_HASH()` equals the configured `ZK_RANGE_HASH` +- `aggregateVerifier.ZK_AGGREGATE_HASH()` equals the configured `ZK_AGGREGATE_HASH` +- all other AggregateVerifier immutables (`ZK_VERIFIER`, `TEE_VERIFIER`, `DELAYED_WETH`, `CONFIG_HASH`, etc.) match the previous AggregateVerifier diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/Makefile b/setup-templates/template-upgrade-zk-and-tee-hash/Makefile new file mode 100644 index 00000000..3e44f2ae --- /dev/null +++ b/setup-templates/template-upgrade-zk-and-tee-hash/Makefile @@ -0,0 +1,79 @@ +include ../../Makefile +include ../../Multisig.mk +include ../.env +include .env + +SIGNER_TOOL_PATH = ../../signer-tool +RPC_URL = $(L1_RPC_URL) +DEPLOYER = $(shell cast wallet address --ledger --mnemonic-derivation-path $(LEDGER_HD_PATH)) +UPDATE_VERIFIER_HASHES_SCRIPT_NAME = script/UpdateVerifierHashes.s.sol:UpdateVerifierHashes +UPDATE_VERIFIER_HASHES_CB_SENDER = $(shell cast call $(CB_MULTISIG) "getOwners()(address[])" --rpc-url $(L1_RPC_URL) | tr -d '[]' | cut -d',' -f1) +UPDATE_VERIFIER_HASHES_SC_SENDER = $(shell cast call $(BASE_SECURITY_COUNCIL) "getOwners()(address[])" --rpc-url $(L1_RPC_URL) | tr -d '[]' | cut -d',' -f1) + +.PHONY: deps +deps: install-eip712sign clean-lib forge-deps clone-oz-upgradeable checkout-base-contracts-commit task-extra-deps + +.PHONY: task-extra-deps +task-extra-deps: + forge install --no-git github.com/base/op-enclave@a2d5398f04c3a8e4df929d58ee638ba4a037bfec + forge install --no-git github.com/risc0/risc0-ethereum@a78ac4a52fe9cfa14120c3b496430f0d42e1d8d3 + forge install --no-git github.com/succinctlabs/sp1-contracts@22c4a47cd0a388cb4e25b4f2513954e4275c74ca + git clone --no-checkout https://github.com/OpenZeppelin/openzeppelin-contracts.git lib/openzeppelin-contracts-v5 && \ + cd lib/openzeppelin-contracts-v5 && git checkout dbb6104ce834628e473d2173bbc9d47f81a9eec3 + git clone --no-checkout https://github.com/Vectorized/solady.git lib/solady-v0.0.245 && \ + cd lib/solady-v0.0.245 && git checkout e0ef35adb0ccd1032794731a995cb599bba7b537 + +.PHONY: validate-config +validate-config: + @test -n "$(BASE_CONTRACTS_COMMIT)" || (echo "BASE_CONTRACTS_COMMIT required" && exit 1) + @test -n "$(GAME_TYPE)" || (echo "GAME_TYPE required" && exit 1) + @test -n "$(TEE_IMAGE_HASH)" || (echo "TEE_IMAGE_HASH required" && exit 1) + @test -n "$(ZK_RANGE_HASH)" || (echo "ZK_RANGE_HASH required" && exit 1) + @test -n "$(ZK_AGGREGATE_HASH)" || (echo "ZK_AGGREGATE_HASH required" && exit 1) + @test -n "$(PROXY_ADMIN_OWNER)" || (echo "PROXY_ADMIN_OWNER required" && exit 1) + @test -n "$(DISPUTE_GAME_FACTORY_PROXY)" || (echo "DISPUTE_GAME_FACTORY_PROXY required" && exit 1) + @echo "Configuration validated successfully" + +## +# Deployment (EOA) +## +.PHONY: deploy-aggregate-verifier +deploy-aggregate-verifier: validate-config +ifndef VERIFIER_API_KEY + $(error VERIFIER_API_KEY is not set) +endif + forge script --rpc-url $(L1_RPC_URL) script/DeployAggregateVerifier.s.sol:DeployAggregateVerifier \ + --ledger --hd-paths $(LEDGER_HD_PATH) --broadcast --verify \ + --verifier custom \ + --verifier-url "https://api.etherscan.io/v2/api?chainid=$(L1_CHAIN_ID)" \ + --verifier-api-key $(VERIFIER_API_KEY) \ + -vvvv --sender $(DEPLOYER) + +## +# Update verifier hashes (multisig) +## +.PHONY: gen-validation-update-verifier-hashes-cb +gen-validation-update-verifier-hashes-cb: validate-config deps-signer-tool + $(call GEN_VALIDATION,$(UPDATE_VERIFIER_HASHES_SCRIPT_NAME),$(CB_MULTISIG),$(UPDATE_VERIFIER_HASHES_CB_SENDER),base-signer.json,) + +.PHONY: gen-validation-update-verifier-hashes-sc +gen-validation-update-verifier-hashes-sc: validate-config deps-signer-tool + $(call GEN_VALIDATION,$(UPDATE_VERIFIER_HASHES_SCRIPT_NAME),$(BASE_SECURITY_COUNCIL),$(UPDATE_VERIFIER_HASHES_SC_SENDER),base-signer-2.json,) + +.PHONY: approve-update-verifier-hashes-cb +approve-update-verifier-hashes-cb: validate-config +approve-update-verifier-hashes-cb: SCRIPT_NAME := $(UPDATE_VERIFIER_HASHES_SCRIPT_NAME) +approve-update-verifier-hashes-cb: + $(call MULTISIG_APPROVE,$(CB_MULTISIG),$(SIGNATURES)) + +.PHONY: approve-update-verifier-hashes-sc +approve-update-verifier-hashes-sc: validate-config +approve-update-verifier-hashes-sc: SCRIPT_NAME := $(UPDATE_VERIFIER_HASHES_SCRIPT_NAME) +approve-update-verifier-hashes-sc: + $(call MULTISIG_APPROVE,$(BASE_SECURITY_COUNCIL),$(SIGNATURES)) + +.PHONY: execute-update-verifier-hashes +execute-update-verifier-hashes: validate-config +execute-update-verifier-hashes: SCRIPT_NAME := $(UPDATE_VERIFIER_HASHES_SCRIPT_NAME) +execute-update-verifier-hashes: + $(call MULTISIG_EXECUTE,0x) diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/README.md b/setup-templates/template-upgrade-zk-and-tee-hash/README.md new file mode 100644 index 00000000..f55660c2 --- /dev/null +++ b/setup-templates/template-upgrade-zk-and-tee-hash/README.md @@ -0,0 +1,65 @@ +# Upgrade ZK and TEE Hash + +Status: TEMPLATE + +## Description + +This template updates the TEE and ZK verifier hashes of a multiproof implementation by: + +- redeploying `AggregateVerifier` with identical immutables, overriding `TEE_IMAGE_HASH`, `ZK_RANGE_HASH`, and `ZK_AGGREGATE_HASH` +- pointing `DisputeGameFactory.gameImpls(gameType)` at the new `AggregateVerifier` + +## Setup + +From the repository root: + +```bash +make setup-upgrade-zk-and-tee-hash network= +cd /-upgrade-zk-and-tee-hash +``` + +Fill in all required values in `.env`: + +- `BASE_CONTRACTS_COMMIT` +- `GAME_TYPE` +- `TEE_IMAGE_HASH` +- `ZK_RANGE_HASH` +- `ZK_AGGREGATE_HASH` +- `PROXY_ADMIN_OWNER` +- `DISPUTE_GAME_FACTORY_PROXY` + +Then install dependencies and build: + +```bash +make deps +forge build +``` + +## Procedure + +### Sign task + +#### 1. Update repo + +```bash +cd contract-deployments +git pull +``` + +#### 2. Run signing tool + +```bash +cd contract-deployments +make sign-task +``` + +#### 3. Open the UI at [http://localhost:3000](http://localhost:3000) + +- Select the correct signer role from the list of available users to sign. +- After completion, close the signer tool with `Ctrl + C`. + +#### 4. Send signature to facilitator + +Copy the signature output and send it to the designated facilitator via the agreed communication channel. + +For facilitator instructions, see `FACILITATOR.md`. \ No newline at end of file diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/foundry.toml b/setup-templates/template-upgrade-zk-and-tee-hash/foundry.toml new file mode 100644 index 00000000..ff55e277 --- /dev/null +++ b/setup-templates/template-upgrade-zk-and-tee-hash/foundry.toml @@ -0,0 +1,36 @@ +[profile.default] +src = 'src' +out = 'out' +libs = ['lib'] +broadcast = 'records' +fs_permissions = [{ access = "read-write", path = "./" }] +optimizer = true +optimizer_runs = 200 +auto_detect_solc = true +evm_version = "prague" +via-ir = false +remappings = [ + '@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts', + '@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts', + '@base-contracts/=lib/contracts/', + '@solady/=lib/solady/src/', + '@solady-v0.0.245/=lib/solady-v0.0.245/src/', + 'forge-std/=lib/forge-std/src/', + 'interfaces/dispute/=lib/contracts/interfaces/dispute/', + 'interfaces/L1/=lib/contracts/interfaces/L1/', + 'interfaces/legacy/=lib/contracts/interfaces/legacy/', + 'interfaces/multiproof/=lib/contracts/interfaces/multiproof/', + 'interfaces/universal/=lib/contracts/interfaces/universal/', + 'src/L1/=lib/contracts/src/L1/', + 'src/libraries/=lib/contracts/src/libraries/', + 'src/dispute/=lib/contracts/src/dispute/', + 'src/universal/=lib/contracts/src/universal/', + 'lib/op-enclave/=lib/op-enclave/', + 'openzeppelin/=lib/risc0-ethereum/lib/openzeppelin-contracts/', + '@lib-keccak/=lib/lib-keccak/contracts/lib/', + 'interfaces/cannon/=lib/contracts/interfaces/cannon/', + 'src/cannon/=lib/contracts/src/cannon/', +] + +[lint] +lint_on_build = false diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol b/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol new file mode 100644 index 00000000..871d5895 --- /dev/null +++ b/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import {Script, console} from "forge-std/Script.sol"; + +import {IAnchorStateRegistry} from "interfaces/dispute/IAnchorStateRegistry.sol"; +import {IDelayedWETH} from "interfaces/dispute/IDelayedWETH.sol"; +import {IDisputeGameFactory} from "interfaces/dispute/IDisputeGameFactory.sol"; +import {IVerifier} from "interfaces/multiproof/IVerifier.sol"; + +import {GameType} from "@base-contracts/src/dispute/lib/Types.sol"; +import {AggregateVerifier} from "@base-contracts/src/multiproof/AggregateVerifier.sol"; + +/// @notice Redeploys AggregateVerifier with updated TEE_IMAGE_HASH, ZK_RANGE_HASH, +/// and ZK_AGGREGATE_HASH. All other immutables (including the existing ZkVerifier) +/// are read on-chain from the current AggregateVerifier to guarantee continuity. +contract DeployAggregateVerifier is Script { + // Task config from .env. + address internal immutable disputeGameFactoryProxyEnv; + GameType internal immutable gameTypeEnv; + bytes32 internal immutable teeImageHashEnv; + bytes32 internal immutable zkRangeHashEnv; + bytes32 internal immutable zkAggregateHashEnv; + + // Live multiproof implementation currently registered in the DGF. + address internal immutable currentAggregateVerifier; + + // Immutable constructor args copied from the live AggregateVerifier. + GameType internal immutable currentGameType; + IAnchorStateRegistry internal immutable currentAnchorStateRegistry; + IDelayedWETH internal immutable currentDelayedWeth; + address internal immutable currentTeeVerifier; + address internal immutable currentZkVerifier; + bytes32 internal immutable currentConfigHash; + uint256 internal immutable currentL2ChainId; + uint256 internal immutable currentBlockInterval; + uint256 internal immutable currentIntermediateBlockInterval; + + // Deployment output written to addresses.json. + address public aggregateVerifier; + + constructor() { + disputeGameFactoryProxyEnv = vm.envAddress("DISPUTE_GAME_FACTORY_PROXY"); + gameTypeEnv = GameType.wrap(uint32(vm.envUint("GAME_TYPE"))); + teeImageHashEnv = vm.envBytes32("TEE_IMAGE_HASH"); + zkRangeHashEnv = vm.envBytes32("ZK_RANGE_HASH"); + zkAggregateHashEnv = vm.envBytes32("ZK_AGGREGATE_HASH"); + + currentAggregateVerifier = address(IDisputeGameFactory(disputeGameFactoryProxyEnv).gameImpls(gameTypeEnv)); + + AggregateVerifier currentAggregate = AggregateVerifier(currentAggregateVerifier); + currentGameType = currentAggregate.gameType(); + currentAnchorStateRegistry = currentAggregate.anchorStateRegistry(); + currentDelayedWeth = currentAggregate.DELAYED_WETH(); + currentTeeVerifier = address(currentAggregate.TEE_VERIFIER()); + currentZkVerifier = address(currentAggregate.ZK_VERIFIER()); + currentConfigHash = currentAggregate.CONFIG_HASH(); + currentL2ChainId = currentAggregate.L2_CHAIN_ID(); + currentBlockInterval = currentAggregate.BLOCK_INTERVAL(); + currentIntermediateBlockInterval = currentAggregate.INTERMEDIATE_BLOCK_INTERVAL(); + } + + function setUp() public view { + require(currentAggregateVerifier != address(0), "current aggregate verifier not found"); + require( + GameType.unwrap(AggregateVerifier(currentAggregateVerifier).gameType()) == GameType.unwrap(gameTypeEnv), + "current game type mismatch" + ); + require(currentZkVerifier != address(0), "current zk verifier not found"); + require(teeImageHashEnv != bytes32(0), "tee image hash not set"); + require(zkRangeHashEnv != bytes32(0), "zk range hash not set"); + require(zkAggregateHashEnv != bytes32(0), "zk aggregate hash not set"); + + // Verify new hashes differ from current. + AggregateVerifier currentAggregate = AggregateVerifier(currentAggregateVerifier); + require( + teeImageHashEnv != currentAggregate.TEE_IMAGE_HASH() || zkRangeHashEnv != currentAggregate.ZK_RANGE_HASH() + || zkAggregateHashEnv != currentAggregate.ZK_AGGREGATE_HASH(), + "all hashes are identical to the current aggregate verifier" + ); + } + + function run() external { + vm.startBroadcast(); + + aggregateVerifier = address( + new AggregateVerifier({ + gameType_: currentGameType, + anchorStateRegistry_: currentAnchorStateRegistry, + delayedWETH: currentDelayedWeth, + teeVerifier: IVerifier(currentTeeVerifier), + zkVerifier: IVerifier(currentZkVerifier), + teeImageHash: teeImageHashEnv, + zkHashes: AggregateVerifier.ZkHashes({rangeHash: zkRangeHashEnv, aggregateHash: zkAggregateHashEnv}), + configHash: currentConfigHash, + l2ChainId: currentL2ChainId, + blockInterval: currentBlockInterval, + intermediateBlockInterval: currentIntermediateBlockInterval + }) + ); + + vm.stopBroadcast(); + + _postCheck(); + _writeAddresses(); + } + + function _postCheck() internal view { + AggregateVerifier currentAggregate = AggregateVerifier(currentAggregateVerifier); + AggregateVerifier av = AggregateVerifier(aggregateVerifier); + + // Verify updated hashes. + require(av.TEE_IMAGE_HASH() == teeImageHashEnv, "aggregate tee image hash mismatch"); + require(av.ZK_RANGE_HASH() == zkRangeHashEnv, "aggregate zk range hash mismatch"); + require(av.ZK_AGGREGATE_HASH() == zkAggregateHashEnv, "aggregate zk aggregate hash mismatch"); + + // Verify all other immutables are preserved from the current AggregateVerifier. + require(GameType.unwrap(av.gameType()) == GameType.unwrap(currentGameType), "aggregate game type mismatch"); + require(address(av.anchorStateRegistry()) == address(currentAnchorStateRegistry), "aggregate asr mismatch"); + require( + address(av.DISPUTE_GAME_FACTORY()) == address(currentAggregate.DISPUTE_GAME_FACTORY()), + "aggregate dgf mismatch" + ); + require(address(av.DELAYED_WETH()) == address(currentDelayedWeth), "aggregate delayed weth mismatch"); + require(address(av.TEE_VERIFIER()) == currentTeeVerifier, "aggregate tee verifier mismatch"); + require(address(av.ZK_VERIFIER()) == currentZkVerifier, "aggregate zk verifier mismatch"); + require(av.CONFIG_HASH() == currentConfigHash, "aggregate config hash mismatch"); + require(av.L2_CHAIN_ID() == currentL2ChainId, "aggregate l2 chain id mismatch"); + require(av.BLOCK_INTERVAL() == currentBlockInterval, "aggregate block interval mismatch"); + require( + av.INTERMEDIATE_BLOCK_INTERVAL() == currentIntermediateBlockInterval, + "aggregate intermediate interval mismatch" + ); + } + + function _writeAddresses() internal { + console.log("AggregateVerifier:", aggregateVerifier); + + string memory root = "root"; + string memory json = + vm.serializeAddress({objectKey: root, valueKey: "aggregateVerifier", value: aggregateVerifier}); + vm.writeJson({json: json, path: "addresses.json"}); + } +} diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/script/UpdateVerifierHashes.s.sol b/setup-templates/template-upgrade-zk-and-tee-hash/script/UpdateVerifierHashes.s.sol new file mode 100644 index 00000000..c0358214 --- /dev/null +++ b/setup-templates/template-upgrade-zk-and-tee-hash/script/UpdateVerifierHashes.s.sol @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import {Vm} from "forge-std/Vm.sol"; + +import {MultisigScript, Enum} from "@base-contracts/script/universal/MultisigScript.sol"; +import {Simulation} from "@base-contracts/script/universal/Simulation.sol"; +import {GameType} from "@base-contracts/src/dispute/lib/Types.sol"; +import {AggregateVerifier} from "@base-contracts/src/multiproof/AggregateVerifier.sol"; + +interface IDisputeGameFactoryAdmin { + function owner() external view returns (address); + function gameImpls(GameType gameType) external view returns (address); + function setImplementation(GameType gameType, address impl, bytes calldata args) external; +} + +/// @notice Updates the live multiproof implementation in the DisputeGameFactory to +/// the newly deployed AggregateVerifier carrying updated TEE_IMAGE_HASH, +/// ZK_RANGE_HASH, and ZK_AGGREGATE_HASH. +contract UpdateVerifierHashes is MultisigScript { + // Task config from .env. + address internal immutable ownerSafeEnv; + address internal immutable disputeGameFactoryProxyEnv; + GameType internal immutable gameTypeEnv; + bytes32 internal immutable teeImageHashEnv; + bytes32 internal immutable zkRangeHashEnv; + bytes32 internal immutable zkAggregateHashEnv; + + // Live onchain state. + address internal immutable currentAggregateVerifier; + + // Deployment output produced by the EOA script and read from addresses.json. + address internal immutable nextAggregateVerifier; + GameType internal immutable nextGameType; + + constructor() { + ownerSafeEnv = vm.envAddress("PROXY_ADMIN_OWNER"); + disputeGameFactoryProxyEnv = vm.envAddress("DISPUTE_GAME_FACTORY_PROXY"); + gameTypeEnv = GameType.wrap(uint32(vm.envUint("GAME_TYPE"))); + teeImageHashEnv = vm.envBytes32("TEE_IMAGE_HASH"); + zkRangeHashEnv = vm.envBytes32("ZK_RANGE_HASH"); + zkAggregateHashEnv = vm.envBytes32("ZK_AGGREGATE_HASH"); + + currentAggregateVerifier = IDisputeGameFactoryAdmin(disputeGameFactoryProxyEnv).gameImpls(gameTypeEnv); + + string memory root = vm.projectRoot(); + string memory path = string.concat(root, "/addresses.json"); + string memory json = vm.readFile(path); + nextAggregateVerifier = vm.parseJsonAddress({json: json, key: ".aggregateVerifier"}); + + nextGameType = AggregateVerifier(nextAggregateVerifier).gameType(); + } + + function setUp() public view { + require(IDisputeGameFactoryAdmin(disputeGameFactoryProxyEnv).owner() == ownerSafeEnv, "dgf owner mismatch"); + + require(currentAggregateVerifier != address(0), "current aggregate verifier not found"); + + AggregateVerifier currentAggregate = AggregateVerifier(currentAggregateVerifier); + require( + GameType.unwrap(currentAggregate.gameType()) == GameType.unwrap(gameTypeEnv), "current game type mismatch" + ); + + require(nextAggregateVerifier != address(0), "next aggregate verifier not set"); + require(nextAggregateVerifier != currentAggregateVerifier, "next aggregate verifier equals current"); + + // Validate the new AggregateVerifier carries the expected hashes. + AggregateVerifier nextAggregate = AggregateVerifier(nextAggregateVerifier); + + require(GameType.unwrap(nextGameType) == GameType.unwrap(gameTypeEnv), "next game type mismatch"); + require(nextAggregate.TEE_IMAGE_HASH() == teeImageHashEnv, "next aggregate tee image hash mismatch"); + require(nextAggregate.ZK_RANGE_HASH() == zkRangeHashEnv, "next aggregate zk range hash mismatch"); + require(nextAggregate.ZK_AGGREGATE_HASH() == zkAggregateHashEnv, "next aggregate zk aggregate hash mismatch"); + + // Validate all other immutables are preserved. + require( + address(nextAggregate.anchorStateRegistry()) == address(currentAggregate.anchorStateRegistry()), + "next aggregate asr mismatch" + ); + require( + address(nextAggregate.DISPUTE_GAME_FACTORY()) == address(currentAggregate.DISPUTE_GAME_FACTORY()), + "next aggregate dgf mismatch" + ); + require( + address(nextAggregate.DELAYED_WETH()) == address(currentAggregate.DELAYED_WETH()), + "next aggregate delayed weth mismatch" + ); + require( + address(nextAggregate.TEE_VERIFIER()) == address(currentAggregate.TEE_VERIFIER()), + "next aggregate tee verifier mismatch" + ); + require( + address(nextAggregate.ZK_VERIFIER()) == address(currentAggregate.ZK_VERIFIER()), + "next aggregate zk verifier mismatch" + ); + require(nextAggregate.CONFIG_HASH() == currentAggregate.CONFIG_HASH(), "next aggregate config hash mismatch"); + require(nextAggregate.L2_CHAIN_ID() == currentAggregate.L2_CHAIN_ID(), "next aggregate l2 chain id mismatch"); + require( + nextAggregate.BLOCK_INTERVAL() == currentAggregate.BLOCK_INTERVAL(), + "next aggregate block interval mismatch" + ); + require( + nextAggregate.INTERMEDIATE_BLOCK_INTERVAL() == currentAggregate.INTERMEDIATE_BLOCK_INTERVAL(), + "next aggregate intermediate interval mismatch" + ); + } + + function _buildCalls() internal view override returns (Call[] memory) { + Call[] memory calls = new Call[](1); + + calls[0] = Call({ + operation: Enum.Operation.Call, + target: disputeGameFactoryProxyEnv, + data: abi.encodeCall(IDisputeGameFactoryAdmin.setImplementation, (nextGameType, nextAggregateVerifier, "")), + value: 0 + }); + + return calls; + } + + function _postCheck(Vm.AccountAccess[] memory, Simulation.Payload memory) internal view override { + IDisputeGameFactoryAdmin dgf = IDisputeGameFactoryAdmin(disputeGameFactoryProxyEnv); + AggregateVerifier currentAggregate = AggregateVerifier(currentAggregateVerifier); + AggregateVerifier nextAggregate = AggregateVerifier(nextAggregateVerifier); + + // Verify DGF now points to the new AggregateVerifier. + require(dgf.gameImpls(nextGameType) == nextAggregateVerifier, "dgf aggregate verifier mismatch"); + + // Verify updated hashes. + require(nextAggregate.TEE_IMAGE_HASH() == teeImageHashEnv, "next aggregate tee image hash mismatch"); + require(nextAggregate.ZK_RANGE_HASH() == zkRangeHashEnv, "next aggregate zk range hash mismatch"); + require(nextAggregate.ZK_AGGREGATE_HASH() == zkAggregateHashEnv, "next aggregate zk aggregate hash mismatch"); + + // Verify all other immutables are preserved. + require( + address(nextAggregate.anchorStateRegistry()) == address(currentAggregate.anchorStateRegistry()), + "next aggregate asr mismatch" + ); + require( + address(nextAggregate.DISPUTE_GAME_FACTORY()) == address(currentAggregate.DISPUTE_GAME_FACTORY()), + "next aggregate dgf mismatch" + ); + require( + address(nextAggregate.DELAYED_WETH()) == address(currentAggregate.DELAYED_WETH()), + "next aggregate delayed weth mismatch" + ); + require( + address(nextAggregate.TEE_VERIFIER()) == address(currentAggregate.TEE_VERIFIER()), + "next aggregate tee verifier mismatch" + ); + require( + address(nextAggregate.ZK_VERIFIER()) == address(currentAggregate.ZK_VERIFIER()), + "next aggregate zk verifier mismatch" + ); + require(nextAggregate.CONFIG_HASH() == currentAggregate.CONFIG_HASH(), "next aggregate config hash mismatch"); + require(nextAggregate.L2_CHAIN_ID() == currentAggregate.L2_CHAIN_ID(), "next aggregate l2 chain id mismatch"); + require( + nextAggregate.BLOCK_INTERVAL() == currentAggregate.BLOCK_INTERVAL(), + "next aggregate block interval mismatch" + ); + require( + nextAggregate.INTERMEDIATE_BLOCK_INTERVAL() == currentAggregate.INTERMEDIATE_BLOCK_INTERVAL(), + "next aggregate intermediate interval mismatch" + ); + } + + function _ownerSafe() internal view override returns (address) { + return ownerSafeEnv; + } +} From 22e415fdb0e341dbfff690ef7445bd010b3b8f69 Mon Sep 17 00:00:00 2001 From: Mihir Wadekar Date: Tue, 2 Jun 2026 11:07:27 -0700 Subject: [PATCH 2/4] fix: polish zk tee hash template --- .../FACILITATOR.md | 4 +- .../template-upgrade-zk-and-tee-hash/Makefile | 20 +++++----- .../README.md | 4 +- .../script/DeployAggregateVerifier.s.sol | 39 +++++++++---------- .../script/UpdateVerifierHashes.s.sol | 24 ++++++------ 5 files changed, 43 insertions(+), 48 deletions(-) diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/FACILITATOR.md b/setup-templates/template-upgrade-zk-and-tee-hash/FACILITATOR.md index 745c8e7f..08758997 100644 --- a/setup-templates/template-upgrade-zk-and-tee-hash/FACILITATOR.md +++ b/setup-templates/template-upgrade-zk-and-tee-hash/FACILITATOR.md @@ -17,7 +17,7 @@ make deploy-aggregate-verifier VERIFIER_API_KEY=... `make deploy-aggregate-verifier` runs `DeployAggregateVerifier`: - redeploys `AggregateVerifier` with the same immutables as the existing one, overriding `TEE_IMAGE_HASH`, `ZK_RANGE_HASH`, and `ZK_AGGREGATE_HASH` -- reuses the existing `ZkVerifier` from the current on-chain AggregateVerifier +- reuses the existing `ZkVerifier` from the current onchain AggregateVerifier - writes `aggregateVerifier` to `addresses.json` Expected `addresses.json` keys: @@ -60,7 +60,7 @@ make gen-validation-update-verifier-hashes-sc This produces: - `validations/base-signer.json` -- `validations/base-signer-2.json` +- `validations/security-council-signer.json` ## Execute the transaction diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/Makefile b/setup-templates/template-upgrade-zk-and-tee-hash/Makefile index 3e44f2ae..8f3c6952 100644 --- a/setup-templates/template-upgrade-zk-and-tee-hash/Makefile +++ b/setup-templates/template-upgrade-zk-and-tee-hash/Makefile @@ -5,23 +5,23 @@ include .env SIGNER_TOOL_PATH = ../../signer-tool RPC_URL = $(L1_RPC_URL) -DEPLOYER = $(shell cast wallet address --ledger --mnemonic-derivation-path $(LEDGER_HD_PATH)) +DEPLOYER = $(shell $(MISE_EXEC) cast wallet address --ledger --mnemonic-derivation-path $(LEDGER_HD_PATH)) UPDATE_VERIFIER_HASHES_SCRIPT_NAME = script/UpdateVerifierHashes.s.sol:UpdateVerifierHashes -UPDATE_VERIFIER_HASHES_CB_SENDER = $(shell cast call $(CB_MULTISIG) "getOwners()(address[])" --rpc-url $(L1_RPC_URL) | tr -d '[]' | cut -d',' -f1) -UPDATE_VERIFIER_HASHES_SC_SENDER = $(shell cast call $(BASE_SECURITY_COUNCIL) "getOwners()(address[])" --rpc-url $(L1_RPC_URL) | tr -d '[]' | cut -d',' -f1) +UPDATE_VERIFIER_HASHES_CB_SENDER = $(shell $(MISE_EXEC) cast call $(CB_MULTISIG) "getOwners()(address[])" --rpc-url $(L1_RPC_URL) | tr -d '[]' | cut -d',' -f1) +UPDATE_VERIFIER_HASHES_SC_SENDER = $(shell $(MISE_EXEC) cast call $(BASE_SECURITY_COUNCIL) "getOwners()(address[])" --rpc-url $(L1_RPC_URL) | tr -d '[]' | cut -d',' -f1) .PHONY: deps deps: install-eip712sign clean-lib forge-deps clone-oz-upgradeable checkout-base-contracts-commit task-extra-deps .PHONY: task-extra-deps task-extra-deps: - forge install --no-git github.com/base/op-enclave@a2d5398f04c3a8e4df929d58ee638ba4a037bfec - forge install --no-git github.com/risc0/risc0-ethereum@a78ac4a52fe9cfa14120c3b496430f0d42e1d8d3 - forge install --no-git github.com/succinctlabs/sp1-contracts@22c4a47cd0a388cb4e25b4f2513954e4275c74ca + $(MISE_EXEC) forge install --no-git github.com/base/op-enclave@a2d5398f04c3a8e4df929d58ee638ba4a037bfec + $(MISE_EXEC) forge install --no-git github.com/risc0/risc0-ethereum@a78ac4a52fe9cfa14120c3b496430f0d42e1d8d3 + $(MISE_EXEC) forge install --no-git github.com/succinctlabs/sp1-contracts@22c4a47cd0a388cb4e25b4f2513954e4275c74ca git clone --no-checkout https://github.com/OpenZeppelin/openzeppelin-contracts.git lib/openzeppelin-contracts-v5 && \ - cd lib/openzeppelin-contracts-v5 && git checkout dbb6104ce834628e473d2173bbc9d47f81a9eec3 + cd lib/openzeppelin-contracts-v5 && git checkout dbb6104ce834628e473d2173bbc9d47f81a9eec3 && rm -rf .git git clone --no-checkout https://github.com/Vectorized/solady.git lib/solady-v0.0.245 && \ - cd lib/solady-v0.0.245 && git checkout e0ef35adb0ccd1032794731a995cb599bba7b537 + cd lib/solady-v0.0.245 && git checkout e0ef35adb0ccd1032794731a995cb599bba7b537 && rm -rf .git .PHONY: validate-config validate-config: @@ -42,7 +42,7 @@ deploy-aggregate-verifier: validate-config ifndef VERIFIER_API_KEY $(error VERIFIER_API_KEY is not set) endif - forge script --rpc-url $(L1_RPC_URL) script/DeployAggregateVerifier.s.sol:DeployAggregateVerifier \ + $(MISE_EXEC) forge script --rpc-url $(L1_RPC_URL) script/DeployAggregateVerifier.s.sol:DeployAggregateVerifier \ --ledger --hd-paths $(LEDGER_HD_PATH) --broadcast --verify \ --verifier custom \ --verifier-url "https://api.etherscan.io/v2/api?chainid=$(L1_CHAIN_ID)" \ @@ -58,7 +58,7 @@ gen-validation-update-verifier-hashes-cb: validate-config deps-signer-tool .PHONY: gen-validation-update-verifier-hashes-sc gen-validation-update-verifier-hashes-sc: validate-config deps-signer-tool - $(call GEN_VALIDATION,$(UPDATE_VERIFIER_HASHES_SCRIPT_NAME),$(BASE_SECURITY_COUNCIL),$(UPDATE_VERIFIER_HASHES_SC_SENDER),base-signer-2.json,) + $(call GEN_VALIDATION,$(UPDATE_VERIFIER_HASHES_SCRIPT_NAME),$(BASE_SECURITY_COUNCIL),$(UPDATE_VERIFIER_HASHES_SC_SENDER),security-council-signer.json,) .PHONY: approve-update-verifier-hashes-cb approve-update-verifier-hashes-cb: validate-config diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/README.md b/setup-templates/template-upgrade-zk-and-tee-hash/README.md index f55660c2..dd0ceb38 100644 --- a/setup-templates/template-upgrade-zk-and-tee-hash/README.md +++ b/setup-templates/template-upgrade-zk-and-tee-hash/README.md @@ -1,6 +1,6 @@ # Upgrade ZK and TEE Hash -Status: TEMPLATE +Status: READY TO SIGN ## Description @@ -62,4 +62,4 @@ make sign-task Copy the signature output and send it to the designated facilitator via the agreed communication channel. -For facilitator instructions, see `FACILITATOR.md`. \ No newline at end of file +For facilitator instructions, see `FACILITATOR.md`. diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol b/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol index 871d5895..46407201 100644 --- a/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol +++ b/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol @@ -13,33 +13,33 @@ import {AggregateVerifier} from "@base-contracts/src/multiproof/AggregateVerifie /// @notice Redeploys AggregateVerifier with updated TEE_IMAGE_HASH, ZK_RANGE_HASH, /// and ZK_AGGREGATE_HASH. All other immutables (including the existing ZkVerifier) -/// are read on-chain from the current AggregateVerifier to guarantee continuity. +/// are read onchain from the current AggregateVerifier to guarantee continuity. contract DeployAggregateVerifier is Script { // Task config from .env. - address internal immutable disputeGameFactoryProxyEnv; - GameType internal immutable gameTypeEnv; - bytes32 internal immutable teeImageHashEnv; - bytes32 internal immutable zkRangeHashEnv; - bytes32 internal immutable zkAggregateHashEnv; + address internal disputeGameFactoryProxyEnv; + GameType internal gameTypeEnv; + bytes32 internal teeImageHashEnv; + bytes32 internal zkRangeHashEnv; + bytes32 internal zkAggregateHashEnv; // Live multiproof implementation currently registered in the DGF. - address internal immutable currentAggregateVerifier; + address internal currentAggregateVerifier; // Immutable constructor args copied from the live AggregateVerifier. - GameType internal immutable currentGameType; - IAnchorStateRegistry internal immutable currentAnchorStateRegistry; - IDelayedWETH internal immutable currentDelayedWeth; - address internal immutable currentTeeVerifier; - address internal immutable currentZkVerifier; - bytes32 internal immutable currentConfigHash; - uint256 internal immutable currentL2ChainId; - uint256 internal immutable currentBlockInterval; - uint256 internal immutable currentIntermediateBlockInterval; + GameType internal currentGameType; + IAnchorStateRegistry internal currentAnchorStateRegistry; + IDelayedWETH internal currentDelayedWeth; + address internal currentTeeVerifier; + address internal currentZkVerifier; + bytes32 internal currentConfigHash; + uint256 internal currentL2ChainId; + uint256 internal currentBlockInterval; + uint256 internal currentIntermediateBlockInterval; // Deployment output written to addresses.json. address public aggregateVerifier; - constructor() { + function setUp() public { disputeGameFactoryProxyEnv = vm.envAddress("DISPUTE_GAME_FACTORY_PROXY"); gameTypeEnv = GameType.wrap(uint32(vm.envUint("GAME_TYPE"))); teeImageHashEnv = vm.envBytes32("TEE_IMAGE_HASH"); @@ -47,6 +47,7 @@ contract DeployAggregateVerifier is Script { zkAggregateHashEnv = vm.envBytes32("ZK_AGGREGATE_HASH"); currentAggregateVerifier = address(IDisputeGameFactory(disputeGameFactoryProxyEnv).gameImpls(gameTypeEnv)); + require(currentAggregateVerifier != address(0), "current aggregate verifier not found"); AggregateVerifier currentAggregate = AggregateVerifier(currentAggregateVerifier); currentGameType = currentAggregate.gameType(); @@ -58,10 +59,7 @@ contract DeployAggregateVerifier is Script { currentL2ChainId = currentAggregate.L2_CHAIN_ID(); currentBlockInterval = currentAggregate.BLOCK_INTERVAL(); currentIntermediateBlockInterval = currentAggregate.INTERMEDIATE_BLOCK_INTERVAL(); - } - function setUp() public view { - require(currentAggregateVerifier != address(0), "current aggregate verifier not found"); require( GameType.unwrap(AggregateVerifier(currentAggregateVerifier).gameType()) == GameType.unwrap(gameTypeEnv), "current game type mismatch" @@ -72,7 +70,6 @@ contract DeployAggregateVerifier is Script { require(zkAggregateHashEnv != bytes32(0), "zk aggregate hash not set"); // Verify new hashes differ from current. - AggregateVerifier currentAggregate = AggregateVerifier(currentAggregateVerifier); require( teeImageHashEnv != currentAggregate.TEE_IMAGE_HASH() || zkRangeHashEnv != currentAggregate.ZK_RANGE_HASH() || zkAggregateHashEnv != currentAggregate.ZK_AGGREGATE_HASH(), diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/script/UpdateVerifierHashes.s.sol b/setup-templates/template-upgrade-zk-and-tee-hash/script/UpdateVerifierHashes.s.sol index c0358214..8225e50c 100644 --- a/setup-templates/template-upgrade-zk-and-tee-hash/script/UpdateVerifierHashes.s.sol +++ b/setup-templates/template-upgrade-zk-and-tee-hash/script/UpdateVerifierHashes.s.sol @@ -19,21 +19,21 @@ interface IDisputeGameFactoryAdmin { /// ZK_RANGE_HASH, and ZK_AGGREGATE_HASH. contract UpdateVerifierHashes is MultisigScript { // Task config from .env. - address internal immutable ownerSafeEnv; - address internal immutable disputeGameFactoryProxyEnv; - GameType internal immutable gameTypeEnv; - bytes32 internal immutable teeImageHashEnv; - bytes32 internal immutable zkRangeHashEnv; - bytes32 internal immutable zkAggregateHashEnv; + address internal ownerSafeEnv; + address internal disputeGameFactoryProxyEnv; + GameType internal gameTypeEnv; + bytes32 internal teeImageHashEnv; + bytes32 internal zkRangeHashEnv; + bytes32 internal zkAggregateHashEnv; // Live onchain state. - address internal immutable currentAggregateVerifier; + address internal currentAggregateVerifier; // Deployment output produced by the EOA script and read from addresses.json. - address internal immutable nextAggregateVerifier; - GameType internal immutable nextGameType; + address internal nextAggregateVerifier; + GameType internal nextGameType; - constructor() { + function setUp() public { ownerSafeEnv = vm.envAddress("PROXY_ADMIN_OWNER"); disputeGameFactoryProxyEnv = vm.envAddress("DISPUTE_GAME_FACTORY_PROXY"); gameTypeEnv = GameType.wrap(uint32(vm.envUint("GAME_TYPE"))); @@ -47,11 +47,10 @@ contract UpdateVerifierHashes is MultisigScript { string memory path = string.concat(root, "/addresses.json"); string memory json = vm.readFile(path); nextAggregateVerifier = vm.parseJsonAddress({json: json, key: ".aggregateVerifier"}); + require(nextAggregateVerifier != address(0), "next aggregate verifier not set"); nextGameType = AggregateVerifier(nextAggregateVerifier).gameType(); - } - function setUp() public view { require(IDisputeGameFactoryAdmin(disputeGameFactoryProxyEnv).owner() == ownerSafeEnv, "dgf owner mismatch"); require(currentAggregateVerifier != address(0), "current aggregate verifier not found"); @@ -61,7 +60,6 @@ contract UpdateVerifierHashes is MultisigScript { GameType.unwrap(currentAggregate.gameType()) == GameType.unwrap(gameTypeEnv), "current game type mismatch" ); - require(nextAggregateVerifier != address(0), "next aggregate verifier not set"); require(nextAggregateVerifier != currentAggregateVerifier, "next aggregate verifier equals current"); // Validate the new AggregateVerifier carries the expected hashes. From 4f82212a8c608f3d580e2ea81c0a218b6a9f0058 Mon Sep 17 00:00:00 2001 From: Mihir Wadekar Date: Tue, 2 Jun 2026 11:48:45 -0700 Subject: [PATCH 3/4] fix: update zk tee template contracts commit --- .../template-upgrade-zk-and-tee-hash/.env | 2 +- .../template-upgrade-zk-and-tee-hash/foundry.toml | 6 +++--- .../script/DeployAggregateVerifier.s.sol | 12 ++++++------ .../script/UpdateVerifierHashes.s.sol | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/.env b/setup-templates/template-upgrade-zk-and-tee-hash/.env index 56a91865..fee20231 100644 --- a/setup-templates/template-upgrade-zk-and-tee-hash/.env +++ b/setup-templates/template-upgrade-zk-and-tee-hash/.env @@ -1,5 +1,5 @@ # Required: Git commit hash for https://github.com/base/contracts -BASE_CONTRACTS_COMMIT=1baa168c9db6a946ae47863ea07295bedb3599a6 +BASE_CONTRACTS_COMMIT=e225648a7ed538e7e28c041d44f3b7a606ba7743 # Network-specific addresses are automatically loaded from {network}/.env via include ../.env. diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/foundry.toml b/setup-templates/template-upgrade-zk-and-tee-hash/foundry.toml index ff55e277..e700572b 100644 --- a/setup-templates/template-upgrade-zk-and-tee-hash/foundry.toml +++ b/setup-templates/template-upgrade-zk-and-tee-hash/foundry.toml @@ -16,14 +16,14 @@ remappings = [ '@solady/=lib/solady/src/', '@solady-v0.0.245/=lib/solady-v0.0.245/src/', 'forge-std/=lib/forge-std/src/', - 'interfaces/dispute/=lib/contracts/interfaces/dispute/', + 'interfaces/dispute/=lib/contracts/interfaces/L1/proofs/', 'interfaces/L1/=lib/contracts/interfaces/L1/', 'interfaces/legacy/=lib/contracts/interfaces/legacy/', - 'interfaces/multiproof/=lib/contracts/interfaces/multiproof/', + 'interfaces/multiproof/=lib/contracts/interfaces/L1/proofs/', 'interfaces/universal/=lib/contracts/interfaces/universal/', 'src/L1/=lib/contracts/src/L1/', 'src/libraries/=lib/contracts/src/libraries/', - 'src/dispute/=lib/contracts/src/dispute/', + 'src/dispute/=lib/contracts/src/L1/proofs/', 'src/universal/=lib/contracts/src/universal/', 'lib/op-enclave/=lib/op-enclave/', 'openzeppelin/=lib/risc0-ethereum/lib/openzeppelin-contracts/', diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol b/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol index 46407201..f26bd471 100644 --- a/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol +++ b/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol @@ -3,13 +3,13 @@ pragma solidity 0.8.15; import {Script, console} from "forge-std/Script.sol"; -import {IAnchorStateRegistry} from "interfaces/dispute/IAnchorStateRegistry.sol"; -import {IDelayedWETH} from "interfaces/dispute/IDelayedWETH.sol"; -import {IDisputeGameFactory} from "interfaces/dispute/IDisputeGameFactory.sol"; -import {IVerifier} from "interfaces/multiproof/IVerifier.sol"; +import {IAnchorStateRegistry} from "interfaces/L1/proofs/IAnchorStateRegistry.sol"; +import {IDelayedWETH} from "interfaces/L1/proofs/IDelayedWETH.sol"; +import {IDisputeGameFactory} from "interfaces/L1/proofs/IDisputeGameFactory.sol"; +import {IVerifier} from "interfaces/L1/proofs/IVerifier.sol"; -import {GameType} from "@base-contracts/src/dispute/lib/Types.sol"; -import {AggregateVerifier} from "@base-contracts/src/multiproof/AggregateVerifier.sol"; +import {GameType} from "@base-contracts/src/libraries/bridge/Types.sol"; +import {AggregateVerifier} from "@base-contracts/src/L1/proofs/AggregateVerifier.sol"; /// @notice Redeploys AggregateVerifier with updated TEE_IMAGE_HASH, ZK_RANGE_HASH, /// and ZK_AGGREGATE_HASH. All other immutables (including the existing ZkVerifier) diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/script/UpdateVerifierHashes.s.sol b/setup-templates/template-upgrade-zk-and-tee-hash/script/UpdateVerifierHashes.s.sol index 8225e50c..10808d1d 100644 --- a/setup-templates/template-upgrade-zk-and-tee-hash/script/UpdateVerifierHashes.s.sol +++ b/setup-templates/template-upgrade-zk-and-tee-hash/script/UpdateVerifierHashes.s.sol @@ -3,10 +3,10 @@ pragma solidity 0.8.15; import {Vm} from "forge-std/Vm.sol"; -import {MultisigScript, Enum} from "@base-contracts/script/universal/MultisigScript.sol"; -import {Simulation} from "@base-contracts/script/universal/Simulation.sol"; -import {GameType} from "@base-contracts/src/dispute/lib/Types.sol"; -import {AggregateVerifier} from "@base-contracts/src/multiproof/AggregateVerifier.sol"; +import {MultisigScript, Enum} from "@base-contracts/scripts/universal/MultisigScript.sol"; +import {Simulation} from "@base-contracts/scripts/universal/Simulation.sol"; +import {AggregateVerifier} from "@base-contracts/src/L1/proofs/AggregateVerifier.sol"; +import {GameType} from "@base-contracts/src/libraries/bridge/Types.sol"; interface IDisputeGameFactoryAdmin { function owner() external view returns (address); From 03524cdd59e66be8480c27f306c42501e7845488 Mon Sep 17 00:00:00 2001 From: Mihir Wadekar Date: Tue, 2 Jun 2026 16:47:48 -0700 Subject: [PATCH 4/4] fix: address zk tee template review comments --- .../template-upgrade-zk-and-tee-hash/.env | 2 +- .../script/DeployAggregateVerifier.s.sol | 43 ++++++++++--------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/.env b/setup-templates/template-upgrade-zk-and-tee-hash/.env index fee20231..fd6e68e0 100644 --- a/setup-templates/template-upgrade-zk-and-tee-hash/.env +++ b/setup-templates/template-upgrade-zk-and-tee-hash/.env @@ -6,7 +6,7 @@ BASE_CONTRACTS_COMMIT=e225648a7ed538e7e28c041d44f3b7a606ba7743 # Multiproof configuration. # The scripts use DISPUTE_GAME_FACTORY_PROXY + GAME_TYPE as the source of truth # to recover the live AggregateVerifier and its current immutables. -GAME_TYPE= +GAME_TYPE=621 # Verifier deployment inputs. TEE_IMAGE_HASH= diff --git a/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol b/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol index f26bd471..43ed248c 100644 --- a/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol +++ b/setup-templates/template-upgrade-zk-and-tee-hash/script/DeployAggregateVerifier.s.sol @@ -16,30 +16,30 @@ import {AggregateVerifier} from "@base-contracts/src/L1/proofs/AggregateVerifier /// are read onchain from the current AggregateVerifier to guarantee continuity. contract DeployAggregateVerifier is Script { // Task config from .env. - address internal disputeGameFactoryProxyEnv; - GameType internal gameTypeEnv; - bytes32 internal teeImageHashEnv; - bytes32 internal zkRangeHashEnv; - bytes32 internal zkAggregateHashEnv; + address internal immutable disputeGameFactoryProxyEnv; + GameType internal immutable gameTypeEnv; + bytes32 internal immutable teeImageHashEnv; + bytes32 internal immutable zkRangeHashEnv; + bytes32 internal immutable zkAggregateHashEnv; // Live multiproof implementation currently registered in the DGF. - address internal currentAggregateVerifier; + address internal immutable currentAggregateVerifier; // Immutable constructor args copied from the live AggregateVerifier. - GameType internal currentGameType; - IAnchorStateRegistry internal currentAnchorStateRegistry; - IDelayedWETH internal currentDelayedWeth; - address internal currentTeeVerifier; - address internal currentZkVerifier; - bytes32 internal currentConfigHash; - uint256 internal currentL2ChainId; - uint256 internal currentBlockInterval; - uint256 internal currentIntermediateBlockInterval; + GameType internal immutable currentGameType; + IAnchorStateRegistry internal immutable currentAnchorStateRegistry; + IDelayedWETH internal immutable currentDelayedWeth; + address internal immutable currentTeeVerifier; + address internal immutable currentZkVerifier; + bytes32 internal immutable currentConfigHash; + uint256 internal immutable currentL2ChainId; + uint256 internal immutable currentBlockInterval; + uint256 internal immutable currentIntermediateBlockInterval; // Deployment output written to addresses.json. address public aggregateVerifier; - function setUp() public { + constructor() { disputeGameFactoryProxyEnv = vm.envAddress("DISPUTE_GAME_FACTORY_PROXY"); gameTypeEnv = GameType.wrap(uint32(vm.envUint("GAME_TYPE"))); teeImageHashEnv = vm.envBytes32("TEE_IMAGE_HASH"); @@ -47,7 +47,6 @@ contract DeployAggregateVerifier is Script { zkAggregateHashEnv = vm.envBytes32("ZK_AGGREGATE_HASH"); currentAggregateVerifier = address(IDisputeGameFactory(disputeGameFactoryProxyEnv).gameImpls(gameTypeEnv)); - require(currentAggregateVerifier != address(0), "current aggregate verifier not found"); AggregateVerifier currentAggregate = AggregateVerifier(currentAggregateVerifier); currentGameType = currentAggregate.gameType(); @@ -59,17 +58,19 @@ contract DeployAggregateVerifier is Script { currentL2ChainId = currentAggregate.L2_CHAIN_ID(); currentBlockInterval = currentAggregate.BLOCK_INTERVAL(); currentIntermediateBlockInterval = currentAggregate.INTERMEDIATE_BLOCK_INTERVAL(); + } - require( - GameType.unwrap(AggregateVerifier(currentAggregateVerifier).gameType()) == GameType.unwrap(gameTypeEnv), - "current game type mismatch" - ); + function setUp() public view { + require(currentAggregateVerifier != address(0), "current aggregate verifier not found"); + require(GameType.unwrap(currentGameType) == GameType.unwrap(gameTypeEnv), "current game type mismatch"); + require(currentTeeVerifier != address(0), "current tee verifier not found"); require(currentZkVerifier != address(0), "current zk verifier not found"); require(teeImageHashEnv != bytes32(0), "tee image hash not set"); require(zkRangeHashEnv != bytes32(0), "zk range hash not set"); require(zkAggregateHashEnv != bytes32(0), "zk aggregate hash not set"); // Verify new hashes differ from current. + AggregateVerifier currentAggregate = AggregateVerifier(currentAggregateVerifier); require( teeImageHashEnv != currentAggregate.TEE_IMAGE_HASH() || zkRangeHashEnv != currentAggregate.ZK_RANGE_HASH() || zkAggregateHashEnv != currentAggregate.ZK_AGGREGATE_HASH(),