Skip to content

Commit

Permalink
feat: Support deployment and verification of upgradeable SpokePools (#…
Browse files Browse the repository at this point in the history
…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]>
  • Loading branch information
3 people authored Apr 25, 2023
1 parent 4f83f54 commit b37510c
Show file tree
Hide file tree
Showing 79 changed files with 1,325 additions and 253 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ jobs:
id: release
uses: manovotny/[email protected]

# Perform installs, run tests, run a build step, etc. here, as needed.
- run: yarn

# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v3
with:
node-version: "16.x"
always-auth: true
registry-url: "https://registry.npmjs.org"

# Perform installs, run tests, run a build step, etc. here, as needed.
- run: yarn

# The last two steps will publish the package. Note that we're using
# information from the `release` step above (I told you we'd use it
# later). Notice the `if` statements on both steps...
Expand Down
40 changes: 26 additions & 14 deletions deploy/003_deploy_optimism_spokepool.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,38 @@
import "hardhat-deploy";
import { HardhatRuntimeEnvironment } from "hardhat/types/runtime";

const func = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getNamedAccounts, companionNetworks } = hre;
const { deploy } = deployments;
import hre from "hardhat";
import { getContractFactory } from "../utils";

const func = async function () {
const { upgrades, companionNetworks, run, getNamedAccounts } = hre;
const { deployer } = await getNamedAccounts();

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

await deploy("Optimism_SpokePool", {
from: deployer,
log: true,
skipIfAlreadyDeployed: true,
args: [
hubPool.address, // Set hub pool as cross domain admin since it delegatecalls the Optimism_Adapter logic.
hubPool.address,
"0x0000000000000000000000000000000000000000", // timer
],
// Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's
// with deprecated spoke pool.
// Set hub pool as cross domain admin since it delegatecalls the Adapter logic.
const constructorArgs = [1_000_000, hubPool.address, hubPool.address];
const spokePool = await upgrades.deployProxy(
await getContractFactory("Optimism_SpokePool", deployer),
constructorArgs,
{
kind: "uups",
}
);
const instance = await spokePool.deployed();
console.log(`SpokePool deployed @ ${instance.address}`);
const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address);
console.log(`Implementation deployed @ ${implementationAddress}`);

// hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed
// is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy
// to the implementation's ABI on etherscan.
// https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify
await run("verify:verify", {
address: instance.address,
});
};
module.exports = func;
Expand Down
51 changes: 33 additions & 18 deletions deploy/005_deploy_arbitrum_spokepool.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,47 @@
import "hardhat-deploy";
import { HardhatRuntimeEnvironment } from "hardhat/types/runtime";

import hre from "hardhat";
import { L2_ADDRESS_MAP } from "./consts";
import { getContractFactory } from "../utils";

const func = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getNamedAccounts, companionNetworks, getChainId } = hre;
const { deploy } = deployments;

const { deployer } = await getNamedAccounts();
const func = async function () {
const { upgrades, companionNetworks, run, getChainId, getNamedAccounts } = hre;

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

const chainId = parseInt(await getChainId());
const { deployer } = await getNamedAccounts();

// Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's
// with deprecated spoke pool.
// Set hub pool as cross domain admin since it delegatecalls the Adapter logic.
const constructorArgs = [
1_000_000,
L2_ADDRESS_MAP[chainId].l2GatewayRouter,
hubPool.address,
hubPool.address,
L2_ADDRESS_MAP[chainId].l2Weth,
];
const spokePool = await upgrades.deployProxy(
await getContractFactory("Arbitrum_SpokePool", deployer),
constructorArgs,
{
kind: "uups",
}
);
const instance = await spokePool.deployed();
console.log(`SpokePool deployed @ ${instance.address}`);
const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address);
console.log(`Implementation deployed @ ${implementationAddress}`);

await deploy("Arbitrum_SpokePool", {
from: deployer,
log: true,
skipIfAlreadyDeployed: true,
args: [
L2_ADDRESS_MAP[chainId].l2GatewayRouter, // _l2GatewayRouter
hubPool.address, // Set hub pool as cross domain admin since it delegatecalls the Optimism_Adapter logic.
hubPool.address,
L2_ADDRESS_MAP[chainId].l2Weth, // l2Weth
"0x0000000000000000000000000000000000000000", // timer
],
// hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed
// is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy
// to the implementation's ABI on etherscan.
// https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify
await run("verify:verify", {
address: instance.address,
});
};
module.exports = func;
Expand Down
40 changes: 30 additions & 10 deletions deploy/007_deploy_ethereum_spokepool.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,45 @@
import "hardhat-deploy";
import { HardhatRuntimeEnvironment } from "hardhat/types/runtime";

import hre from "hardhat";
import { getContractFactory } from "../utils";

import { L1_ADDRESS_MAP } from "./consts";

const func = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getNamedAccounts, getChainId } = hre;
const { deploy } = deployments;
export async function printProxyVerificationInstructions() {}

const { deployer } = await getNamedAccounts();
const func = async function () {
const { deployments, getChainId, upgrades, run, getNamedAccounts } = hre;

const chainId = parseInt(await getChainId());
const { deployer } = await getNamedAccounts();

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

await deploy("Ethereum_SpokePool", {
from: deployer,
log: true,
skipIfAlreadyDeployed: true,
args: [hubPool.address, L1_ADDRESS_MAP[chainId].weth, "0x0000000000000000000000000000000000000000"],
// Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's
// with deprecated spoke pool.
const constructorArgs = [1_000_000, hubPool.address, L1_ADDRESS_MAP[chainId].weth];
const spokePool = await upgrades.deployProxy(
await getContractFactory("Ethereum_SpokePool", deployer),
constructorArgs,
{
kind: "uups",
}
);
const instance = await spokePool.deployed();
console.log(`SpokePool deployed @ ${instance.address}`);
const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address);
console.log(`Implementation deployed @ ${implementationAddress}`);

// hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed
// is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy
// to the implementation's ABI on etherscan.
// https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify
await run("verify:verify", {
address: instance.address,
});

// Transfer ownership to hub pool.
};
module.exports = func;
func.tags = ["EthereumSpokePool", "mainnet"];
57 changes: 36 additions & 21 deletions deploy/011_deploy_polygon_spokepool.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,48 @@
import "hardhat-deploy";
import { HardhatRuntimeEnvironment } from "hardhat/types/runtime";

import hre from "hardhat";
import { L2_ADDRESS_MAP } from "./consts";
import { getContractFactory } from "../utils";

const func = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getNamedAccounts, getChainId } = hre;
const { deploy } = deployments;
const func = async function () {
const { upgrades, run, getChainId, getNamedAccounts } = hre;

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

const chainId = parseInt(await getChainId());
const l1HubPool = await hre.companionNetworks.l1.deployments.get("HubPool");
const polygonTokenBridger = await deployments.get("PolygonTokenBridger");
// Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's
// with deprecated spoke pool.
// Set hub pool as cross domain admin since it delegatecalls the Adapter logic.
const constructorArgs = [
1_000_000,
// The same token bridger must be deployed on mainnet and polygon, so its easier
// to reuse it.
"0x0330E9b4D0325cCfF515E81DFbc7754F2a02ac57",
hubPool.address,
hubPool.address,
L2_ADDRESS_MAP[chainId].wMatic,
L2_ADDRESS_MAP[chainId].fxChild,
];
const spokePool = await upgrades.deployProxy(
await getContractFactory("Polygon_SpokePool", deployer),
constructorArgs,
{
kind: "uups",
}
);
const instance = await spokePool.deployed();
console.log(`SpokePool deployed @ ${instance.address}`);
const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address);
console.log(`Implementation deployed @ ${implementationAddress}`);

await deploy("Polygon_SpokePool", {
from: deployer,
log: true,
skipIfAlreadyDeployed: true,
args: [
polygonTokenBridger.address,
l1HubPool.address,
l1HubPool.address,
L2_ADDRESS_MAP[chainId].wMatic,
L2_ADDRESS_MAP[chainId].fxChild,
"0x0000000000000000000000000000000000000000",
],
// hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed
// is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy
// to the implementation's ABI on etherscan.
// https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify
await run("verify:verify", {
address: instance.address,
});
};

module.exports = func;
func.dependencies = ["PolygonTokenBridgerL2"];
func.tags = ["PolygonSpokePool", "polygon"];
39 changes: 23 additions & 16 deletions deploy/013_deploy_boba_spokepool.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
import "hardhat-deploy";
import { HardhatRuntimeEnvironment } from "hardhat/types/runtime";
import hre from "hardhat";
import { getContractFactory } from "../utils";

const func = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getNamedAccounts, companionNetworks } = hre;
const { deploy } = deployments;

const { deployer } = await getNamedAccounts();
const func = async function () {
const { upgrades, companionNetworks, run, getNamedAccounts } = hre;

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

// Boba Spoke pool uses the same implementation as optimism, with no changes.
await deploy("Boba_SpokePool", {
from: deployer,
log: true,
skipIfAlreadyDeployed: true,
args: [
hubPool.address, // Set hub pool as cross domain admin since it delegatecalls the Optimism_Adapter logic.
hubPool.address,
"0x0000000000000000000000000000000000000000", // timer
],
// Initialize deposit counter to very high number of deposits to avoid duplicate deposit ID's
// with deprecated spoke pool.
// Set hub pool as cross domain admin since it delegatecalls the Adapter logic.
const { deployer } = await getNamedAccounts();
const constructorArgs = [1_000_000, hubPool.address, hubPool.address];
const spokePool = await upgrades.deployProxy(await getContractFactory("Boba_SpokePool", deployer), constructorArgs, {
kind: "uups",
});
const instance = await spokePool.deployed();
console.log(`SpokePool deployed @ ${instance.address}`);
const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address);
console.log(`Implementation deployed @ ${implementationAddress}`);

// hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed
// is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy
// to the implementation's ABI on etherscan.
// https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify
await run("verify:verify", {
address: instance.address,
});
};
module.exports = func;
Expand Down
51 changes: 32 additions & 19 deletions deploy/016_deploy_zksync_spokepool.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,46 @@
import "hardhat-deploy";
import { HardhatRuntimeEnvironment } from "hardhat/types/runtime";

import hre from "hardhat";
import { L2_ADDRESS_MAP } from "./consts";
import { getContractFactory } from "../utils";

const func = async function (hre: HardhatRuntimeEnvironment) {
const { companionNetworks, getChainId, getNamedAccounts, deployments } = hre;
const { deploy } = deployments;

const { deployer } = await getNamedAccounts();
const func = async function () {
const { upgrades, companionNetworks, run, getChainId, getNamedAccounts } = hre;

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

const chainId = parseInt(await getChainId());
const { deployer } = await getNamedAccounts();

// Set hub pool as cross domain admin since it delegatecalls the Adapter logic.
const constructorArgs = [
0, // Start at 0 since this first time we're deploying this spoke pool. On future upgrades increase this.
L2_ADDRESS_MAP[chainId].zkErc20Bridge,
L2_ADDRESS_MAP[chainId].zkEthBridge,
hubPool.address,
hubPool.address,
L2_ADDRESS_MAP[chainId].l2Weth,
];
const spokePool = await upgrades.deployProxy(
await getContractFactory("ZkSync_SpokePool", deployer),
constructorArgs,
{
kind: "uups",
}
);
const instance = await spokePool.deployed();
console.log(`SpokePool deployed @ ${instance.address}`);
const implementationAddress = await upgrades.erc1967.getImplementationAddress(instance.address);
console.log(`Implementation deployed @ ${implementationAddress}`);

await deploy("ZkSync_SpokePool", {
from: deployer,
log: true,
skipIfAlreadyDeployed: true,
args: [
L2_ADDRESS_MAP[chainId].zkErc20Bridge,
L2_ADDRESS_MAP[chainId].zkEthBridge,
hubPool.address, // Set hub pool as cross domain admin since it delegatecalls the ZkSync_Adapter logic.
hubPool.address,
L2_ADDRESS_MAP[chainId].l2Weth, // l2Weth
"0x0000000000000000000000000000000000000000", // timer
],
// hardhat-upgrades overrides the `verify` task that ships with `hardhat` so that if the address passed
// is a proxy, hardhat will first verify the implementation and then the proxy and also link the proxy
// to the implementation's ABI on etherscan.
// https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#verify
await run("verify:verify", {
address: instance.address,
});
};
module.exports = func;
Expand Down
Loading

0 comments on commit b37510c

Please sign in to comment.