Skip to content

Commit b37510c

Browse files
nicholaspaidohakipxrl
authored
feat: Support deployment and verification of upgradeable SpokePools (#272)
* feat: Support deployment and verification of upgradeable SpokePools `hardhat-upgrades` has some useful libraries we can use to deploy and verify proxies. I've tested these all out on prod. * Update deployment files * Update SpokePool.Fixture.ts * Update deployments.json * fix Signed-off-by: nicholaspai <[email protected]> * fix tests Signed-off-by: nicholaspai <[email protected]> * Update package.json * WIP * add arbitrum goerli redeployment * Update package.json * build: workaround @uma/common package browser compatibility (#273) * Move utils to src/utils * Update publish.yml * Update package.json * Update test/SpokePool.SlowRelay.ts Co-authored-by: Paul <[email protected]> * WIP * WIP * WIP * Update upgradeTo.ts * WIP * Deploy mainnet * bump OZ-contracts-upgradeable version * Update package.json * Update package.json * fix: Execute fill with updated message and recipient When sped up, updated message and recipient are not used * Update SpokePool.Relay.ts * WIP * Update test/SpokePool.SlowRelay.ts Co-authored-by: Paul <[email protected]> * Update yarn.lock * Add signer to getContractFactory call * Update Arbitrum_Adapter.json * Delete d89e3488271f97cf1ea0bdb289d28ad2.json * Block partial fills with messages * Update package.json * Update SpokePool.sol * Block partial fills with messages * Update SpokePool.SlowRelay.ts * deploy new contracts * Add helper scripts * fix * improve(SpokePool): Pass fillCompleted and relayer to acrossMessageHandler Signed-off-by: nicholaspai <[email protected]> * fix test Signed-off-by: nicholaspai <[email protected]> * Fix * Revert "Update SpokePool.SlowRelay.ts" This reverts commit 59a9225. * Update SpokePool.sol * fix * New deployments * Update package.json * Remove sdk-v2 circular import --------- Signed-off-by: nicholaspai <[email protected]> Co-authored-by: Dong-Ha Kim <[email protected]> Co-authored-by: Paul <[email protected]>
1 parent 4f83f54 commit b37510c

File tree

79 files changed

+1325
-253
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1325
-253
lines changed

.github/workflows/publish.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ jobs:
2323
id: release
2424
uses: manovotny/[email protected]
2525

26-
# Perform installs, run tests, run a build step, etc. here, as needed.
27-
- run: yarn
28-
2926
# Setup .npmrc file to publish to npm
3027
- uses: actions/setup-node@v3
3128
with:
3229
node-version: "16.x"
3330
always-auth: true
3431
registry-url: "https://registry.npmjs.org"
3532

33+
# Perform installs, run tests, run a build step, etc. here, as needed.
34+
- run: yarn
35+
3636
# The last two steps will publish the package. Note that we're using
3737
# information from the `release` step above (I told you we'd use it
3838
# later). Notice the `if` statements on both steps...

deploy/003_deploy_optimism_spokepool.ts

+26-14
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,38 @@
11
import "hardhat-deploy";
2-
import { HardhatRuntimeEnvironment } from "hardhat/types/runtime";
3-
4-
const func = async function (hre: HardhatRuntimeEnvironment) {
5-
const { deployments, getNamedAccounts, companionNetworks } = hre;
6-
const { deploy } = deployments;
2+
import hre from "hardhat";
3+
import { getContractFactory } from "../utils";
74

5+
const func = async function () {
6+
const { upgrades, companionNetworks, run, getNamedAccounts } = hre;
87
const { deployer } = await getNamedAccounts();
98

109
// Grab L1 addresses:
1110
const { deployments: l1Deployments } = companionNetworks.l1;
1211
const hubPool = await l1Deployments.get("HubPool");
1312
console.log(`Using l1 hub pool @ ${hubPool.address}`);
1413

15-
await deploy("Optimism_SpokePool", {
16-
from: deployer,
17-
log: true,
18-
skipIfAlreadyDeployed: true,
19-
args: [
20-
hubPool.address, // Set hub pool as cross domain admin since it delegatecalls the Optimism_Adapter logic.
21-
hubPool.address,
22-
"0x0000000000000000000000000000000000000000", // timer
23-
],
14+
// Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's
15+
// with deprecated spoke pool.
16+
// Set hub pool as cross domain admin since it delegatecalls the Adapter logic.
17+
const constructorArgs = [1_000_000, hubPool.address, hubPool.address];
18+
const spokePool = await upgrades.deployProxy(
19+
await getContractFactory("Optimism_SpokePool", deployer),
20+
constructorArgs,
21+
{
22+
kind: "uups",
23+
}
24+
);
25+
const instance = await spokePool.deployed();
26+
console.log(`SpokePool deployed @ ${instance.address}`);
27+
const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address);
28+
console.log(`Implementation deployed @ ${implementationAddress}`);
29+
30+
// hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed
31+
// is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy
32+
// to the implementation's ABI on etherscan.
33+
// https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify
34+
await run("verify:verify", {
35+
address: instance.address,
2436
});
2537
};
2638
module.exports = func;

deploy/005_deploy_arbitrum_spokepool.ts

+33-18
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,47 @@
11
import "hardhat-deploy";
2-
import { HardhatRuntimeEnvironment } from "hardhat/types/runtime";
3-
2+
import hre from "hardhat";
43
import { L2_ADDRESS_MAP } from "./consts";
4+
import { getContractFactory } from "../utils";
55

6-
const func = async function (hre: HardhatRuntimeEnvironment) {
7-
const { deployments, getNamedAccounts, companionNetworks, getChainId } = hre;
8-
const { deploy } = deployments;
9-
10-
const { deployer } = await getNamedAccounts();
6+
const func = async function () {
7+
const { upgrades, companionNetworks, run, getChainId, getNamedAccounts } = hre;
118

129
// Grab L1 addresses:
1310
const { deployments: l1Deployments } = companionNetworks.l1;
1411
const hubPool = await l1Deployments.get("HubPool");
1512
console.log(`Using l1 hub pool @ ${hubPool.address}`);
1613

1714
const chainId = parseInt(await getChainId());
15+
const { deployer } = await getNamedAccounts();
16+
17+
// Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's
18+
// with deprecated spoke pool.
19+
// Set hub pool as cross domain admin since it delegatecalls the Adapter logic.
20+
const constructorArgs = [
21+
1_000_000,
22+
L2_ADDRESS_MAP[chainId].l2GatewayRouter,
23+
hubPool.address,
24+
hubPool.address,
25+
L2_ADDRESS_MAP[chainId].l2Weth,
26+
];
27+
const spokePool = await upgrades.deployProxy(
28+
await getContractFactory("Arbitrum_SpokePool", deployer),
29+
constructorArgs,
30+
{
31+
kind: "uups",
32+
}
33+
);
34+
const instance = await spokePool.deployed();
35+
console.log(`SpokePool deployed @ ${instance.address}`);
36+
const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address);
37+
console.log(`Implementation deployed @ ${implementationAddress}`);
1838

19-
await deploy("Arbitrum_SpokePool", {
20-
from: deployer,
21-
log: true,
22-
skipIfAlreadyDeployed: true,
23-
args: [
24-
L2_ADDRESS_MAP[chainId].l2GatewayRouter, // _l2GatewayRouter
25-
hubPool.address, // Set hub pool as cross domain admin since it delegatecalls the Optimism_Adapter logic.
26-
hubPool.address,
27-
L2_ADDRESS_MAP[chainId].l2Weth, // l2Weth
28-
"0x0000000000000000000000000000000000000000", // timer
29-
],
39+
// hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed
40+
// is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy
41+
// to the implementation's ABI on etherscan.
42+
// https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify
43+
await run("verify:verify", {
44+
address: instance.address,
3045
});
3146
};
3247
module.exports = func;
+30-10
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,45 @@
11
import "hardhat-deploy";
2-
import { HardhatRuntimeEnvironment } from "hardhat/types/runtime";
2+
3+
import hre from "hardhat";
4+
import { getContractFactory } from "../utils";
35

46
import { L1_ADDRESS_MAP } from "./consts";
57

6-
const func = async function (hre: HardhatRuntimeEnvironment) {
7-
const { deployments, getNamedAccounts, getChainId } = hre;
8-
const { deploy } = deployments;
8+
export async function printProxyVerificationInstructions() {}
99

10-
const { deployer } = await getNamedAccounts();
10+
const func = async function () {
11+
const { deployments, getChainId, upgrades, run, getNamedAccounts } = hre;
1112

1213
const chainId = parseInt(await getChainId());
14+
const { deployer } = await getNamedAccounts();
1315

1416
const hubPool = await deployments.get("HubPool");
1517
console.log(`Using l1 hub pool @ ${hubPool.address}`);
1618

17-
await deploy("Ethereum_SpokePool", {
18-
from: deployer,
19-
log: true,
20-
skipIfAlreadyDeployed: true,
21-
args: [hubPool.address, L1_ADDRESS_MAP[chainId].weth, "0x0000000000000000000000000000000000000000"],
19+
// Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's
20+
// with deprecated spoke pool.
21+
const constructorArgs = [1_000_000, hubPool.address, L1_ADDRESS_MAP[chainId].weth];
22+
const spokePool = await upgrades.deployProxy(
23+
await getContractFactory("Ethereum_SpokePool", deployer),
24+
constructorArgs,
25+
{
26+
kind: "uups",
27+
}
28+
);
29+
const instance = await spokePool.deployed();
30+
console.log(`SpokePool deployed @ ${instance.address}`);
31+
const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address);
32+
console.log(`Implementation deployed @ ${implementationAddress}`);
33+
34+
// hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed
35+
// is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy
36+
// to the implementation's ABI on etherscan.
37+
// https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify
38+
await run("verify:verify", {
39+
address: instance.address,
2240
});
41+
42+
// Transfer ownership to hub pool.
2343
};
2444
module.exports = func;
2545
func.tags = ["EthereumSpokePool", "mainnet"];
+36-21
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,48 @@
11
import "hardhat-deploy";
2-
import { HardhatRuntimeEnvironment } from "hardhat/types/runtime";
3-
2+
import hre from "hardhat";
43
import { L2_ADDRESS_MAP } from "./consts";
4+
import { getContractFactory } from "../utils";
55

6-
const func = async function (hre: HardhatRuntimeEnvironment) {
7-
const { deployments, getNamedAccounts, getChainId } = hre;
8-
const { deploy } = deployments;
6+
const func = async function () {
7+
const { upgrades, run, getChainId, getNamedAccounts } = hre;
98

9+
const chainId = parseInt(await getChainId());
10+
const hubPool = await hre.companionNetworks.l1.deployments.get("HubPool");
1011
const { deployer } = await getNamedAccounts();
1112

12-
const chainId = parseInt(await getChainId());
13-
const l1HubPool = await hre.companionNetworks.l1.deployments.get("HubPool");
14-
const polygonTokenBridger = await deployments.get("PolygonTokenBridger");
13+
// Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's
14+
// with deprecated spoke pool.
15+
// Set hub pool as cross domain admin since it delegatecalls the Adapter logic.
16+
const constructorArgs = [
17+
1_000_000,
18+
// The same token bridger must be deployed on mainnet and polygon, so its easier
19+
// to reuse it.
20+
"0x0330E9b4D0325cCfF515E81DFbc7754F2a02ac57",
21+
hubPool.address,
22+
hubPool.address,
23+
L2_ADDRESS_MAP[chainId].wMatic,
24+
L2_ADDRESS_MAP[chainId].fxChild,
25+
];
26+
const spokePool = await upgrades.deployProxy(
27+
await getContractFactory("Polygon_SpokePool", deployer),
28+
constructorArgs,
29+
{
30+
kind: "uups",
31+
}
32+
);
33+
const instance = await spokePool.deployed();
34+
console.log(`SpokePool deployed @ ${instance.address}`);
35+
const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address);
36+
console.log(`Implementation deployed @ ${implementationAddress}`);
1537

16-
await deploy("Polygon_SpokePool", {
17-
from: deployer,
18-
log: true,
19-
skipIfAlreadyDeployed: true,
20-
args: [
21-
polygonTokenBridger.address,
22-
l1HubPool.address,
23-
l1HubPool.address,
24-
L2_ADDRESS_MAP[chainId].wMatic,
25-
L2_ADDRESS_MAP[chainId].fxChild,
26-
"0x0000000000000000000000000000000000000000",
27-
],
38+
// hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed
39+
// is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy
40+
// to the implementation's ABI on etherscan.
41+
// https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify
42+
await run("verify:verify", {
43+
address: instance.address,
2844
});
2945
};
3046

3147
module.exports = func;
32-
func.dependencies = ["PolygonTokenBridgerL2"];
3348
func.tags = ["PolygonSpokePool", "polygon"];

deploy/013_deploy_boba_spokepool.ts

+23-16
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,34 @@
11
import "hardhat-deploy";
2-
import { HardhatRuntimeEnvironment } from "hardhat/types/runtime";
2+
import hre from "hardhat";
3+
import { getContractFactory } from "../utils";
34

4-
const func = async function (hre: HardhatRuntimeEnvironment) {
5-
const { deployments, getNamedAccounts, companionNetworks } = hre;
6-
const { deploy } = deployments;
7-
8-
const { deployer } = await getNamedAccounts();
5+
const func = async function () {
6+
const { upgrades, companionNetworks, run, getNamedAccounts } = hre;
97

108
// Grab L1 addresses:
119
const { deployments: l1Deployments } = companionNetworks.l1;
1210
const hubPool = await l1Deployments.get("HubPool");
1311
console.log(`Using l1 hub pool @ ${hubPool.address}`);
1412

15-
// Boba Spoke pool uses the same implementation as optimism, with no changes.
16-
await deploy("Boba_SpokePool", {
17-
from: deployer,
18-
log: true,
19-
skipIfAlreadyDeployed: true,
20-
args: [
21-
hubPool.address, // Set hub pool as cross domain admin since it delegatecalls the Optimism_Adapter logic.
22-
hubPool.address,
23-
"0x0000000000000000000000000000000000000000", // timer
24-
],
13+
// Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's
14+
// with deprecated spoke pool.
15+
// Set hub pool as cross domain admin since it delegatecalls the Adapter logic.
16+
const { deployer } = await getNamedAccounts();
17+
const constructorArgs = [1_000_000, hubPool.address, hubPool.address];
18+
const spokePool = await upgrades.deployProxy(await getContractFactory("Boba_SpokePool", deployer), constructorArgs, {
19+
kind: "uups",
20+
});
21+
const instance = await spokePool.deployed();
22+
console.log(`SpokePool deployed @ ${instance.address}`);
23+
const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address);
24+
console.log(`Implementation deployed @ ${implementationAddress}`);
25+
26+
// hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed
27+
// is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy
28+
// to the implementation's ABI on etherscan.
29+
// https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify
30+
await run("verify:verify", {
31+
address: instance.address,
2532
});
2633
};
2734
module.exports = func;

deploy/016_deploy_zksync_spokepool.ts

+32-19
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,46 @@
11
import "hardhat-deploy";
2-
import { HardhatRuntimeEnvironment } from "hardhat/types/runtime";
3-
2+
import hre from "hardhat";
43
import { L2_ADDRESS_MAP } from "./consts";
4+
import { getContractFactory } from "../utils";
55

6-
const func = async function (hre: HardhatRuntimeEnvironment) {
7-
const { companionNetworks, getChainId, getNamedAccounts, deployments } = hre;
8-
const { deploy } = deployments;
9-
10-
const { deployer } = await getNamedAccounts();
6+
const func = async function () {
7+
const { upgrades, companionNetworks, run, getChainId, getNamedAccounts } = hre;
118

129
// Grab L1 addresses:
1310
const { deployments: l1Deployments } = companionNetworks.l1;
1411
const hubPool = await l1Deployments.get("HubPool");
1512
console.log(`Using l1 hub pool @ ${hubPool.address}`);
1613

1714
const chainId = parseInt(await getChainId());
15+
const { deployer } = await getNamedAccounts();
16+
17+
// Set hub pool as cross domain admin since it delegatecalls the Adapter logic.
18+
const constructorArgs = [
19+
0, // Start at 0 since this first time we're deploying this spoke pool. On future upgrades increase this.
20+
L2_ADDRESS_MAP[chainId].zkErc20Bridge,
21+
L2_ADDRESS_MAP[chainId].zkEthBridge,
22+
hubPool.address,
23+
hubPool.address,
24+
L2_ADDRESS_MAP[chainId].l2Weth,
25+
];
26+
const spokePool = await upgrades.deployProxy(
27+
await getContractFactory("ZkSync_SpokePool", deployer),
28+
constructorArgs,
29+
{
30+
kind: "uups",
31+
}
32+
);
33+
const instance = await spokePool.deployed();
34+
console.log(`SpokePool deployed @ ${instance.address}`);
35+
const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address);
36+
console.log(`Implementation deployed @ ${implementationAddress}`);
1837

19-
await deploy("ZkSync_SpokePool", {
20-
from: deployer,
21-
log: true,
22-
skipIfAlreadyDeployed: true,
23-
args: [
24-
L2_ADDRESS_MAP[chainId].zkErc20Bridge,
25-
L2_ADDRESS_MAP[chainId].zkEthBridge,
26-
hubPool.address, // Set hub pool as cross domain admin since it delegatecalls the ZkSync_Adapter logic.
27-
hubPool.address,
28-
L2_ADDRESS_MAP[chainId].l2Weth, // l2Weth
29-
"0x0000000000000000000000000000000000000000", // timer
30-
],
38+
// hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed
39+
// is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy
40+
// to the implementation's ABI on etherscan.
41+
// https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify
42+
await run("verify:verify", {
43+
address: instance.address,
3144
});
3245
};
3346
module.exports = func;

0 commit comments

Comments
 (0)