Skip to content

Commit 44c372b

Browse files
authored
Merge branch 'main' into angelo/selectable
2 parents 233a355 + 6a4eff5 commit 44c372b

File tree

16 files changed

+425
-60
lines changed

16 files changed

+425
-60
lines changed

RELEASE.md

+18-2
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,25 @@
6969

7070
1. Deploy the verifier contract and schedule the update.
7171

72-
2. After the timelock delay has passed (7 days on mainnet chains and 1 second on testnet), finsh the operation to add the new verifier to the router.
72+
2. After the timelock delay has passed (7 days on mainnet chains and 1 second on testnet), finish the operation to add the new verifier to the router.
7373

74-
3. Document the new addresses and version in the `dev.risczero.com` docs.
74+
3. Run the deployment tests to confirm that the state recorded in `deployment.toml` matches the state of the contracts deployed on-chain.
75+
76+
You can run the tests against a single chain with the following command:
77+
78+
```sh
79+
# In the contracts directory.
80+
FOUNDRY_PROFILE=deployment-test forge test -vv --fork-url="$RPC_URL"
81+
```
82+
83+
You can run the tests against all supported chains with the following oneliner:
84+
85+
```sh
86+
# In the contracts directory.
87+
for rpcurl in $(yq eval -e ".chains[].rpc-url" deployment_secrets.toml); do FOUNDRY_PROFILE=deployment-test forge test -vv --fork-url="$rpcurl"; done
88+
```
89+
90+
4. Document the new addresses and version in the `dev.risczero.com` docs.
7591

7692
Use [contracts/generate_contract_address_table.py] to generate the tables. Python 3.11+ is required.
7793

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// Copyright 2024 RISC Zero, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
// SPDX-License-Identifier: Apache-2.0
16+
17+
pragma solidity ^0.8.9;
18+
19+
import {Test} from "forge-std/Test.sol";
20+
import {console2} from "forge-std/console2.sol";
21+
import {TimelockController} from "openzeppelin/contracts/governance/TimelockController.sol";
22+
import {RiscZeroVerifierRouter} from "../src/RiscZeroVerifierRouter.sol";
23+
import {IRiscZeroVerifier} from "../src/IRiscZeroVerifier.sol";
24+
import {ConfigLoader, Deployment, DeploymentLib, VerifierDeployment} from "../src/config/Config.sol";
25+
26+
/// Test designed to be run against a chain with an active deployment of the RISC Zero contracts.
27+
/// Checks that the deployment matches what is recorded in the deployment.toml file.
28+
contract DeploymentTest is Test {
29+
using DeploymentLib for Deployment;
30+
31+
Deployment internal deployment;
32+
33+
TimelockController internal timelockController;
34+
RiscZeroVerifierRouter internal router;
35+
36+
function setUp() external {
37+
string memory configPath = vm.envOr("DEPLOYMENT_CONFIG", string("./deployment.toml"));
38+
console2.log("Loading deployment config from %s", configPath);
39+
ConfigLoader.loadDeploymentConfig(configPath).copyTo(deployment);
40+
41+
// Wrap the control addresses with their respective contract implementations.
42+
// NOTE: These addresses may be zero, so this does not guarantee contracts are deployed.
43+
timelockController = TimelockController(payable(deployment.timelockController));
44+
router = RiscZeroVerifierRouter(deployment.router);
45+
}
46+
47+
function testAdminIsSet() external view {
48+
require(deployment.admin != address(0), "no admin address is set");
49+
}
50+
51+
function testTimelockControllerIsDeployed() external view {
52+
require(address(timelockController) != address(0), "no timelock controller address is set");
53+
require(
54+
keccak256(address(timelockController).code) != keccak256(bytes("")), "timelock controller code is empty"
55+
);
56+
}
57+
58+
function testRouterIsDeployed() external view {
59+
require(address(router) != address(0), "no router address is set");
60+
require(keccak256(address(router).code) != keccak256(bytes("")), "router code is empty");
61+
}
62+
63+
function testTimelockControllerIsConfiguredProperly() external view {
64+
require(
65+
timelockController.hasRole(timelockController.PROPOSER_ROLE(), deployment.admin),
66+
"admin does not have proposer role"
67+
);
68+
require(
69+
timelockController.hasRole(timelockController.EXECUTOR_ROLE(), deployment.admin),
70+
"admin does not have executor role"
71+
);
72+
require(
73+
timelockController.hasRole(timelockController.CANCELLER_ROLE(), deployment.admin),
74+
"admin does not have canceller role"
75+
);
76+
uint256 deployedDelay = timelockController.getMinDelay();
77+
console2.log(
78+
"Min delay on timelock controller is %d; expected value is %d", deployedDelay, deployment.timelockDelay
79+
);
80+
require(
81+
timelockController.getMinDelay() == deployment.timelockDelay,
82+
"timelock controller min delay is not as expected"
83+
);
84+
}
85+
86+
function testVerifierRouterIsConfiguredProperly() external view {
87+
require(router.owner() == address(timelockController), "router is not owned by timelock controller");
88+
89+
for (uint256 i = 0; i < deployment.verifiers.length; i++) {
90+
VerifierDeployment storage verifierConfig = deployment.verifiers[i];
91+
console2.log(
92+
"Checking for deployment to the router of verifier with selector %x and version %s",
93+
uint256(uint32(verifierConfig.selector)),
94+
verifierConfig.version
95+
);
96+
if (verifierConfig.unroutable) {
97+
// When a verifier is specified to be unroutable, confirm that it is indeed not added to the router.
98+
try router.getVerifier(verifierConfig.selector) {
99+
revert("expected router.getVerifier to revert");
100+
} catch (bytes memory err) {
101+
// NOTE: We could allot SelectorRemoved as well here.
102+
require(
103+
keccak256(err)
104+
== keccak256(
105+
abi.encodeWithSelector(
106+
RiscZeroVerifierRouter.SelectorUnknown.selector, verifierConfig.selector
107+
)
108+
)
109+
);
110+
console2.log(
111+
"Verifier with selector %x is unroutable, as configured",
112+
uint256(uint32(verifierConfig.selector))
113+
);
114+
}
115+
continue;
116+
}
117+
118+
IRiscZeroVerifier verifierImpl = router.getVerifier(verifierConfig.selector);
119+
require(address(verifierImpl) != address(0), "verifier impl returned the zero address");
120+
require(keccak256(address(verifierImpl).code) != keccak256(bytes("")), "verifier impl has no deployed code");
121+
// TODO: When SELECTOR is added to the public verifier interface, also check the verifier has the expected selector.
122+
}
123+
}
124+
}

contracts/deployment.toml

+45-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ admin = "0xF616A4f81857CFEe54A4A049Ec187172574bd412"
88

99
# Contracts
1010
timelock-controller = "0x0b144E07A0826182B6b59788c34b32Bfa86Fb711"
11+
timelock-delay = 604800
1112
router = "0x8EaB2D97Dfce405A1692a21b3ff3A172d593D319"
1213

1314
# TODO: Add information for 1.0 contracts.
1415
[[chains.ethereum-mainnet.verifiers]]
16+
version = "1.1.0-rc.2"
17+
unroutable = true
1518
selector = "0x4c630d87"
1619
verifier = "0x5a99469f18a5863D3258E577892589386dFD965E"
1720
estop = "0xB839eA7bBA8e6bB2893ca5252F3f3C13323D74F7"
@@ -34,10 +37,12 @@ admin = "0x3a54A45E44a71020Bd0Af42063B9f23e8b9E387D"
3437

3538
# Contracts
3639
timelock-controller = "0xB4E3306129208cC8e6E75157f75f62eAe0B920a0"
40+
timelock-delay = 1
3741
router = "0x925d8331ddc0a1F0d96E68CF073DFE1d92b69187"
3842

3943
[[chains.ethereum-sepolia.verifiers]]
4044
version = "1.1.0-rc.2"
45+
unroutable = true
4146
selector = "0x4c630d87"
4247
verifier = "0xf4D938c73Bcc124e02A2D6c7557e98838B5E91B4"
4348
estop = "0x1C182869A6bF84DfAc0a70B46e2f9b3aeE9100e1"
@@ -60,9 +65,12 @@ admin = "0x3a54A45E44a71020Bd0Af42063B9f23e8b9E387D"
6065

6166
# Contracts
6267
timelock-controller = "0x8EaB2D97Dfce405A1692a21b3ff3A172d593D319"
68+
timelock-delay = 1
6369
router = "0xf70aBAb028Eb6F4100A24B203E113D94E87DE93C"
6470

6571
[[chains.ethereum-holesky.verifiers]]
72+
version = "1.1.0-rc.2"
73+
unroutable = true
6674
selector = "0x4c630d87"
6775
verifier = "0xDC986a09728F76110FF666eE7b20d99086501d15"
6876
estop = "0x0b144E07A0826182B6b59788c34b32Bfa86Fb711"
@@ -85,9 +93,12 @@ admin = "0xF616A4f81857CFEe54A4A049Ec187172574bd412"
8593

8694
# Contracts
8795
timelock-controller = "0xdc986a09728f76110ff666ee7b20d99086501d15"
96+
timelock-delay = 604800
8897
router = "0x0b144e07a0826182b6b59788c34b32bfa86fb711"
8998

9099
[[chains.arbitrum-mainnet.verifiers]]
100+
version = "1.1.0-rc.2"
101+
unroutable = true
91102
selector = "0x4c630d87"
92103
verifier = "0xBDaEd5bbf8016AfD05Fc4659572e5fEb5854aAD4"
93104
estop = "0x27983ee173aD10E171D17C9c5C14d5baFE997609"
@@ -110,9 +121,12 @@ admin = "0x3a54A45E44a71020Bd0Af42063B9f23e8b9E387D"
110121

111122
# Contracts
112123
timelock-controller = "0xdc986a09728f76110ff666ee7b20d99086501d15"
124+
timelock-delay = 1
113125
router = "0x0b144e07a0826182b6b59788c34b32bfa86fb711"
114126

115127
[[chains.arbitrum-sepolia.verifiers]]
128+
version = "1.1.0-rc.2"
129+
unroutable = true
116130
selector = "0x4c630d87"
117131
verifier = "0xBDaEd5bbf8016AfD05Fc4659572e5fEb5854aAD4"
118132
estop = "0x27983ee173aD10E171D17C9c5C14d5baFE997609"
@@ -135,9 +149,12 @@ admin = "0xF616A4f81857CFEe54A4A049Ec187172574bd412"
135149

136150
# Contracts
137151
timelock-controller = "0xDC986a09728F76110FF666eE7b20d99086501d15"
152+
timelock-delay = 604800
138153
router = "0x0b144E07A0826182B6b59788c34b32Bfa86Fb711"
139154

140155
[[chains.avalanche-mainnet.verifiers]]
156+
version = "1.1.0-rc.2"
157+
unroutable = true
141158
selector = "0x4c630d87"
142159
verifier = "0xBDaEd5bbf8016AfD05Fc4659572e5fEb5854aAD4"
143160
estop = "0x27983ee173aD10E171D17C9c5C14d5baFE997609"
@@ -160,9 +177,12 @@ admin = "0x3a54A45E44a71020Bd0Af42063B9f23e8b9E387D"
160177

161178
# Contracts
162179
timelock-controller = "0xDC986a09728F76110FF666eE7b20d99086501d15"
180+
timelock-delay = 1
163181
router = "0x0b144E07A0826182B6b59788c34b32Bfa86Fb711"
164182

165183
[[chains.avalanche-fuji.verifiers]]
184+
version = "1.1.0-rc.2"
185+
unroutable = true
166186
selector = "0x4c630d87"
167187
verifier = "0xBDaEd5bbf8016AfD05Fc4659572e5fEb5854aAD4"
168188
estop = "0x27983ee173aD10E171D17C9c5C14d5baFE997609"
@@ -185,9 +205,12 @@ admin = "0xF616A4f81857CFEe54A4A049Ec187172574bd412"
185205

186206
# Contracts
187207
timelock-controller = "0xdc986a09728f76110ff666ee7b20d99086501d15"
208+
timelock-delay = 604800
188209
router = "0x0b144e07a0826182b6b59788c34b32bfa86fb711"
189210

190211
[[chains.base-mainnet.verifiers]]
212+
version = "1.1.0-rc.2"
213+
unroutable = true
191214
selector = "0x4c630d87"
192215
verifier = "0xBDaEd5bbf8016AfD05Fc4659572e5fEb5854aAD4"
193216
estop = "0x27983ee173aD10E171D17C9c5C14d5baFE997609"
@@ -210,9 +233,12 @@ admin = "0x3a54A45E44a71020Bd0Af42063B9f23e8b9E387D"
210233

211234
# Contracts
212235
timelock-controller = "0xdc986a09728f76110ff666ee7b20d99086501d15"
236+
timelock-delay = 1
213237
router = "0x0b144e07a0826182b6b59788c34b32bfa86fb711"
214238

215239
[[chains.base-sepolia.verifiers]]
240+
version = "1.1.0-rc.2"
241+
unroutable = true
216242
selector = "0x4c630d87"
217243
verifier = "0x84b943E31e7fAe6072ce5F75eb4694C7D5F9b0cF"
218244
estop = "0x5E36f0D56741013d864d8FEb5950AB0E7Eff9Ab1"
@@ -235,9 +261,12 @@ admin = "0xF616A4f81857CFEe54A4A049Ec187172574bd412"
235261

236262
# Contracts
237263
timelock-controller = "0xdc986a09728f76110ff666ee7b20d99086501d15"
264+
timelock-delay = 604800
238265
router = "0x0b144e07a0826182b6b59788c34b32bfa86fb711"
239266

240267
[[chains.optimism-mainnet.verifiers]]
268+
version = "1.1.0-rc.2"
269+
unroutable = true
241270
selector = "0x4c630d87"
242271
verifier = "0xBDaEd5bbf8016AfD05Fc4659572e5fEb5854aAD4"
243272
estop = "0x27983ee173aD10E171D17C9c5C14d5baFE997609"
@@ -252,19 +281,22 @@ estop = "0x5E36f0D56741013d864d8FEb5950AB0E7Eff9Ab1"
252281

253282
[chains.optimism-sepolia]
254283
name = "Optimism Sepolia"
255-
id = 11110
284+
id = 11155420
256285
etherscan-url = "https://sepolia-optimism.etherscan.io/"
257286

258287
# Accounts
259288
admin = "0x3a54A45E44a71020Bd0Af42063B9f23e8b9E387D"
260289

261290
# Contracts
262291
timelock-controller = "0x2DEfEA335392bb62d01f74e338697C7B31De254C"
292+
timelock-delay = 1
263293
router = "0xB369b4dd27FBfb59921d3A4a3D23AC2fc32FB908"
264294

265295
# NOTE: 1.0 was not deployed to OP Sepolia.
266296

267297
[[chains.optimism-sepolia.verifiers]]
298+
version = "1.1.0-rc.2"
299+
unroutable = true
268300
selector = "0x4c630d87"
269301
verifier = "0xBDaEd5bbf8016AfD05Fc4659572e5fEb5854aAD4"
270302
estop = "0x27983ee173aD10E171D17C9c5C14d5baFE997609"
@@ -287,9 +319,12 @@ admin = "0xF616A4f81857CFEe54A4A049Ec187172574bd412"
287319

288320
# Contracts
289321
timelock-controller = "0xdc986a09728f76110ff666ee7b20d99086501d15"
322+
timelock-delay = 604800
290323
router = "0x0b144e07a0826182b6b59788c34b32bfa86fb711"
291324

292325
[[chains.linea-mainnet.verifiers]]
326+
version = "1.1.0-rc.2"
327+
unroutable = true
293328
selector = "0x4c630d87"
294329
verifier = "0xBDaEd5bbf8016AfD05Fc4659572e5fEb5854aAD4"
295330
estop = "0x27983ee173aD10E171D17C9c5C14d5baFE997609"
@@ -312,6 +347,7 @@ admin = "0x3a54A45E44a71020Bd0Af42063B9f23e8b9E387D"
312347

313348
# Contracts
314349
timelock-controller = "0xBDaEd5bbf8016AfD05Fc4659572e5fEb5854aAD4"
350+
timelock-delay = 1
315351
router = "0x27983ee173aD10E171D17C9c5C14d5baFE997609"
316352

317353
# NOTE: As of the 1.1.0-rc.2 deployment on August 21, Forge could not verify the contracts.
@@ -321,12 +357,15 @@ router = "0x27983ee173aD10E171D17C9c5C14d5baFE997609"
321357
# As a result, the router is deployed, but it is empty and useless.
322358

323359
[[chains.linea-sepolia.verifiers]]
360+
version = "1.1.0-rc.2"
361+
unroutable = true
324362
selector = "0x4c630d87"
325363
verifier = "0x0b144E07A0826182B6b59788c34b32Bfa86Fb711"
326364
estop = "0x8EaB2D97Dfce405A1692a21b3ff3A172d593D319"
327365

328366
[[chains.linea-sepolia.verifiers]]
329367
version = "1.1.0-rc.3"
368+
unroutable = true
330369
selector = "0x50bd1769"
331370
verifier = "0xf70aBAb028Eb6F4100A24B203E113D94E87DE93C"
332371
estop = "0x44c220f0598345195cE99AD6A57aDfFcb9Ea33e7"
@@ -343,9 +382,12 @@ admin = "0xF616A4f81857CFEe54A4A049Ec187172574bd412"
343382

344383
# Contracts
345384
timelock-controller = "0xdc986a09728f76110ff666ee7b20d99086501d15"
385+
timelock-delay = 604800
346386
router = "0x0b144e07a0826182b6b59788c34b32bfa86fb711"
347387

348388
[[chains.polygon-zkevm-mainnet.verifiers]]
389+
version = "1.1.0-rc.2"
390+
unroutable = true
349391
selector = "0x4c630d87"
350392
verifier = "0xBDaEd5bbf8016AfD05Fc4659572e5fEb5854aAD4"
351393
estop = "0x27983ee173aD10E171D17C9c5C14d5baFE997609"
@@ -358,9 +400,10 @@ estop = "0x5E36f0D56741013d864d8FEb5950AB0E7Eff9Ab1"
358400

359401
###
360402

403+
# NOTE: This is the Cardona testnet, which uses Sepolia ETH as it's native currency.
361404
[chains.polygon-zkevm-testnet]
362405
name = "Polygon zkEVM Testnet"
363-
id = 1442
406+
id = 2442
364407
etherscan-url = "https://cardona-zkevm.polygonscan.com/"
365408

366409
# Accounts

contracts/foundry.toml

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
[profile.default]
22
src = "src"
33
out = "out"
4+
test = "test"
45
libs = ["../lib"]
56
ffi = true
67

7-
# See more config options https://github.com/foundry-rs/foundry/tree/master/config
8+
# Profile used to run deployment tests, which check the correctness of contracts as deployed.
9+
# TIP: You can select this profile by setting env var FOUNDRY_PROFILE=deployment-test
10+
[profile.deployment-test]
11+
test = "./deployment-test"
12+
#match_path = "contracts/deployment-test/*"
13+
fs_permissions = [{ access = "read", path = "deployment.toml" }]
14+
15+
# See more config options https://book.getfoundry.sh/static/config.default.toml

contracts/script/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Configurations and deployment state information is stored in `deployment.toml`.
2626
It contains information about each chain (e.g. name, ID, Etherscan URL), and addresses for the timelock, router, and verifier contracts on each chain.
2727

2828
Accompanying the `deployment.toml` file is a `deployment_secrets.toml` file with the following schema.
29-
It is used to store somewhat sensative API keys for RPC services and Etherscan.
29+
It is used to store somewhat sensitive API keys for RPC services and Etherscan.
3030
Note that it does not contain private keys or API keys for Fireblocks.
3131
It should never be committed to `git`, and the API keys should be rotated if this occurs.
3232

0 commit comments

Comments
 (0)