Skip to content

feat: periphery deploy scripts and deployments #812

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 42 commits into
base: march-25-evm-audit
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
db4bf7b
feat(SpokePoolPeriphery): Support multiple exchanges
nicholaspai Nov 27, 2024
df04404
rename
nicholaspai Nov 27, 2024
1954009
Update SpokeV3PoolPeriphery.sol
nicholaspai Nov 27, 2024
fc1ff8f
Update SpokeV3PoolPeriphery.sol
nicholaspai Nov 27, 2024
c1b6d4f
Update SpokeV3PoolPeriphery.sol
nicholaspai Nov 27, 2024
3b3352e
Add unit tests
nicholaspai Nov 27, 2024
aca4b06
Add whitelistExchanges only owner method
nicholaspai Nov 27, 2024
7149287
rename
nicholaspai Nov 27, 2024
dda8499
Remove onlyOwner
nicholaspai Nov 27, 2024
2da9c63
Remove whitelist of exchanges, add proxy to bypass approval abuse
nicholaspai Nov 28, 2024
90e7cd0
Add some protection to callSpokePoolPeriphery
nicholaspai Nov 28, 2024
9511666
Only call swapAndBridge through proxy
nicholaspai Dec 1, 2024
e0bead2
move periphery funcs into proxy
nicholaspai Dec 2, 2024
5494ee5
Update SpokePoolV3Periphery.sol
nicholaspai Dec 3, 2024
b6db47b
remove depositERC20
nicholaspai Dec 3, 2024
66df238
Merge branch 'master' into spokepool-periphery-multiple-exchanges
nicholaspai Dec 4, 2024
d0a9d0f
Update SpokePoolV3Periphery.sol
nicholaspai Dec 4, 2024
6635803
Add back safeTransferFron's to permit funcs
nicholaspai Dec 4, 2024
6b995e5
Merge branch 'master' into spokepool-periphery-multiple-exchanges
nicholaspai Dec 4, 2024
0de384e
Add unit tests that check if calling deposit and swapAndBridge with n…
nicholaspai Dec 5, 2024
100e707
Add interfaces to make sure we don't add new functions as easily
nicholaspai Dec 5, 2024
6db7d87
Add Create2Factory
nicholaspai Dec 6, 2024
3a16809
Merge branch 'master' into spokepool-periphery-multiple-exchanges
nicholaspai Dec 6, 2024
022a8ec
feat: add permit2 entrypoints to the periphery (#782)
bmzig Dec 6, 2024
372d9cb
Merge branch 'master' into spokepool-periphery-multiple-exchanges
nicholaspai Dec 9, 2024
c9017ff
feat: sponsored swap and deposits (#790)
bmzig Dec 18, 2024
9bc7d91
feat: Delete SwapAndBridge and add submission fees to gasless flow (#…
nicholaspai Dec 19, 2024
f4250d0
Update SpokePoolV3Periphery.sol
nicholaspai Dec 19, 2024
9a4ef73
Update SpokePoolPeriphery.t.sol
nicholaspai Dec 19, 2024
494cf4e
feat: periphery deployments
bmzig Dec 19, 2024
6e60050
remove console
bmzig Dec 19, 2024
75373c9
fix comments
bmzig Dec 19, 2024
a340e15
world chain
bmzig Dec 19, 2024
863ef67
add deployments for all networks except zksync and mainnet
bmzig Dec 20, 2024
d59b77c
add zksync deployment
bmzig Dec 20, 2024
1ceeeea
deploy on mainnet
bmzig Dec 23, 2024
26110a9
fix: eip712 types and hashes (#821)
dohaki Dec 24, 2024
c1f6181
refactor comments
bmzig Dec 25, 2024
5a6b3ed
Merge branch 'spokepool-periphery-multiple-exchanges' into bz/periphe…
bmzig Dec 25, 2024
e5dbcb0
new deployments on arb, base, and op
bmzig Dec 25, 2024
424f4dd
redeploy all contracts
bmzig Dec 27, 2024
8a9abb9
Merge branch 'march-25-evm-audit' into bz/peripheryTestDeployments
nicholaspai Mar 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions deploy/059_deploy_create2_factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";

/**
* Usage:
* $ yarn hardhat deploy --network mainnet --tags Create2Factory
*/

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployer } = await hre.getNamedAccounts();
const chainId = parseInt(await hre.getChainId());

const { address: deployment } = await hre.deployments.deploy("Create2Factory", {
from: deployer,
log: true,
skipIfAlreadyDeployed: true,
args: [],
deterministicDeployment: "0x12345678",
maxPriorityFeePerGas: 1,
maxFeePerGas: 10e9,
});

await hre.run("verify:verify", { address: deployment });
};

module.exports = func;
func.tags = ["Create2Factory"];
27 changes: 27 additions & 0 deletions deploy/060_deploy_periphery_proxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";

/**
* Note:
* Both the spoke pool periphery and periphery proxy need to know each other's address. Since the periphery generally contains
* the most logic, the periphery is deployed atomically with the create2factory, while the periphery proxy is deployed asynchronously.
* yarn hardhat deploy --network mainnet --tags SpokePoolPeripheryProxy
*/

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployer } = await hre.getNamedAccounts();
const chainId = parseInt(await hre.getChainId());

const { address: deployment } = await hre.deployments.deploy("SpokePoolPeripheryProxy", {
from: deployer,
log: true,
skipIfAlreadyDeployed: true,
deterministicDeployment: "0x1234567890",
args: [],
});

await hre.run("verify:verify", { address: deployment });
};

module.exports = func;
func.tags = ["SpokePoolPeripheryProxy"];
67 changes: 67 additions & 0 deletions deploy/061_deploy_spokepool_periphery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { getMnemonic } from "@uma/common";
import { DeployFunction } from "hardhat-deploy/types";
import { L1_ADDRESS_MAP, L2_ADDRESS_MAP, WETH } from "./consts";
import { CHAIN_IDs } from "../utils";
import { Contract, ethers } from "ethers";
import deployments from "../deployments/deployments.json";

/**
* Usage:
* $ yarn hardhat deploy --network mainnet --tags SpokePoolPeriphery
*/

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployer } = await hre.getNamedAccounts();
const { network } = hre;
const chainId = parseInt(await hre.getChainId());
const spokePoolAddress = deployments[chainId]?.SpokePool?.address;
if (!spokePoolAddress) throw new Error(`SpokePool entry not found in deployments.json for chain ${chainId}`);
const provider = new ethers.providers.StaticJsonRpcProvider(network.config.url);
const signer = new ethers.Wallet.fromMnemonic(getMnemonic()).connect(provider);

const ethAmount = 0;
const salt = "0x0000000000000000000000000000000000000000000000000000012345678910";

const onL1 = chainId === CHAIN_IDs.MAINNET || chainId === CHAIN_IDs.SEPOLIA;
const create2FactoryAddress = onL1 ? L1_ADDRESS_MAP[chainId].create2Factory : L2_ADDRESS_MAP[chainId].create2Factory;
const permit2 = onL1 ? L1_ADDRESS_MAP[chainId].permit2 : L2_ADDRESS_MAP[chainId].permit2;

// TODO: Should we instead just pass this in as an argument?
const peripheryProxy = onL1
? L1_ADDRESS_MAP[chainId].spokePoolPeripheryProxy
: L2_ADDRESS_MAP[chainId].spokePoolPeripheryProxy;

const factoryArtifact = await hre.artifacts.readArtifact("Create2Factory");
const create2Factory = new Contract(create2FactoryAddress, factoryArtifact.abi, signer);

const peripheryArtifact = await hre.artifacts.readArtifact("SpokePoolV3Periphery");
const periphery = new Contract(create2FactoryAddress, peripheryArtifact.abi); // Address does not matter since we are just using the abi to encode function data.
const initializationCode = await periphery.populateTransaction.initialize(
spokePoolAddress,
WETH[chainId],
peripheryProxy,
permit2
);

// Compute the expected create2 address so that we can verify it. If the address is not this address, then the deployment transaction will fail, since that implies that
// an address was already deployed at this address.
const expectedPeripheryAddress = ethers.utils.getCreate2Address(
create2FactoryAddress,
salt,
ethers.utils.keccak256(peripheryArtifact.bytecode)
);
const deployCalldata = await create2Factory.populateTransaction.deploy(
ethAmount,
salt,
peripheryArtifact.bytecode,
initializationCode.data
);
const pendingTransaction = await signer.sendTransaction(deployCalldata);
await pendingTransaction.wait();

await hre.run("verify:verify", { address: expectedPeripheryAddress });
};

module.exports = func;
func.tags = ["SpokePoolPeriphery"];
42 changes: 42 additions & 0 deletions deploy/062_deploy_periphery_proxy_zk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import assert from "assert";
import * as zk from "zksync-web3";
import { Deployer as zkDeployer } from "@matterlabs/hardhat-zksync-deploy";
import { DeployFunction, DeploymentSubmission } from "hardhat-deploy/types";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { CHAIN_IDs } from "../utils";

/**
* yarn hardhat deploy --network mainnet --tags SpokePoolPeripheryProxyZk
*/

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const contractName = "SpokePoolPeripheryProxy";
const { deployments } = hre;
const chainId = parseInt(await hre.getChainId());
assert(chainId === CHAIN_IDs.ZK_SYNC);

const mnemonic = hre.network.config.accounts.mnemonic;
const wallet = zk.Wallet.fromMnemonic(mnemonic);
const deployer = new zkDeployer(hre, wallet);

const artifact = await deployer.loadArtifact(contractName);
const constructorArgs = [];

const _deployment = await deployer.deploy(artifact, constructorArgs);
const newAddress = _deployment.address;
console.log(`New ${contractName} implementation deployed @ ${newAddress}`);

// Save the deployment manually because OZ's hardhat-upgrades packages bypasses hardhat-deploy.
// See also: https://stackoverflow.com/questions/74870472
const extendedArtifact = await deployments.getExtendedArtifact(contractName);
const deployment: DeploymentSubmission = {
address: newAddress,
...extendedArtifact,
};
await deployments.save(contractName, deployment);

await hre.run("verify:verify", { address: newAddress, constructorArguments: constructorArgs });
};

module.exports = func;
func.tags = ["SpokePoolPeripheryProxyZk"];
55 changes: 55 additions & 0 deletions deploy/063_deploy_spokepool_periphery_zk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { getMnemonic } from "@uma/common";
import { L1_ADDRESS_MAP, L2_ADDRESS_MAP, WETH } from "./consts";
import { CHAIN_IDs } from "../utils";
import { Contract } from "ethers";
import assert from "assert";
import * as zk from "zksync-web3";
import { Deployer as zkDeployer } from "@matterlabs/hardhat-zksync-deploy";
import { DeployFunction, DeploymentSubmission } from "hardhat-deploy/types";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import contractDeployments from "../deployments/deployments.json";

/**
* Usage:
* $ yarn hardhat deploy --network mainnet --tags SpokePoolPeripheryZk
*/

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const contractName = "SpokePoolV3Periphery";
const { network, deployments } = hre;
const chainId = parseInt(await hre.getChainId());

assert(chainId === CHAIN_IDs.ZK_SYNC);
const spokePoolAddress = contractDeployments[chainId]?.SpokePool?.address;
if (!spokePoolAddress) throw new Error(`SpokePool entry not found in deployments.json for chain ${chainId}`);

const signer = zk.Wallet.fromMnemonic(getMnemonic());
const deployer = new zkDeployer(hre, signer);

// We know we are on ZkSync.
const permit2 = L2_ADDRESS_MAP[chainId].permit2;
const peripheryProxy = L2_ADDRESS_MAP[chainId].spokePoolPeripheryProxy;

const peripheryArtifact = await deployer.loadArtifact(contractName);
const periphery = new Contract(spokePoolAddress, peripheryArtifact.abi, deployer.ethWallet); // Address does not matter since we are just using the abi to encode function data.
const initializationCode = await periphery.populateTransaction.initialize(
spokePoolAddress,
WETH[chainId],
peripheryProxy,
permit2
);
const _deployment = await deployer.deploy(peripheryArtifact, []);
const peripheryAddress = _deployment.address;
console.log(`New ${contractName} implementation deployed @ ${peripheryAddress}`);
const extendedArtifact = await deployments.getExtendedArtifact(contractName);
const deployment: DeploymentSubmission = {
address: peripheryAddress,
...extendedArtifact,
};
await deployments.save(contractName, deployment);

await hre.run("verify:verify", { address: peripheryAddress });
};

module.exports = func;
func.tags = ["SpokePoolPeripheryZk"];
32 changes: 32 additions & 0 deletions deploy/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export const L1_ADDRESS_MAP: { [key: number]: { [contractName: string]: string }
l1AlephZeroInbox: "0x56D8EC76a421063e1907503aDd3794c395256AEb",
l1AlephZeroERC20GatewayRouter: "0xeBb17f398ed30d02F2e8733e7c1e5cf566e17812",
donationBox: "0x0d57392895Db5aF3280e9223323e20F3951E81B1",
create2Factory: "0x22dAe400e0F6a330610F3060Be894ab33f9caED0",
spokePoolPeripheryProxy: "0x2d5E44b66bD40267fb816c9537E026545bEbbAC8",
permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
},
[CHAIN_IDs.SEPOLIA]: {
finder: "0xeF684C38F94F48775959ECf2012D7E864ffb9dd4",
Expand Down Expand Up @@ -173,13 +176,24 @@ export const L2_ADDRESS_MAP: { [key: number]: { [contractName: string]: string }
cctpMessageTransmitter: "0xC30362313FBBA5cf9163F0bb16a0e01f01A896ca",
uniswapV3SwapRouter: "0xE592427A0AEce92De3Edee1F18E0157C05861564",
"1inchV6Router": "0x111111125421cA6dc452d289314280a0f8842A65",
create2Factory: "0x22dAe400e0F6a330610F3060Be894ab33f9caED0",
permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
spokePoolPeripheryProxy: "0x2d5E44b66bD40267fb816c9537E026545bEbbAC8",
},
[CHAIN_IDs.BLAST]: {
create2Factory: "0x22dAe400e0F6a330610F3060Be894ab33f9caED0",
permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
spokePoolPeripheryProxy: "0x2d5E44b66bD40267fb816c9537E026545bEbbAC8",
},
[CHAIN_IDs.POLYGON]: {
fxChild: "0x8397259c983751DAf40400790063935a11afa28a",
cctpTokenMessenger: "0x9daF8c91AEFAE50b9c0E69629D3F6Ca40cA3B3FE",
cctpMessageTransmitter: "0xF3be9355363857F3e001be68856A2f96b4C39Ba9",
uniswapV3SwapRouter: "0xE592427A0AEce92De3Edee1F18E0157C05861564",
"1inchV6Router": "0x111111125421cA6dc452d289314280a0f8842A65",
create2Factory: "0x22dAe400e0F6a330610F3060Be894ab33f9caED0",
spokePoolPeripheryProxy: "0x2d5E44b66bD40267fb816c9537E026545bEbbAC8",
permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
},
[CHAIN_IDs.POLYGON_AMOY]: {
fxChild: "0xE5930336866d0388f0f745A2d9207C7781047C0f",
Expand All @@ -189,12 +203,17 @@ export const L2_ADDRESS_MAP: { [key: number]: { [contractName: string]: string }
[CHAIN_IDs.ZK_SYNC]: {
zkErc20Bridge: "0x11f943b2c77b743AB90f4A0Ae7d5A4e7FCA3E102",
"1inchV6Router": "0x6fd4383cB451173D5f9304F041C7BCBf27d561fF",
spokePoolPeripheryProxy: "0x793Ff9Cd09819C537500dFcEB6F61861c1B80dCD",
permit2: "0x0000000000225e31d15943971f47ad3022f714fa",
},
[CHAIN_IDs.OPTIMISM]: {
cctpTokenMessenger: "0x2B4069517957735bE00ceE0fadAE88a26365528f",
cctpMessageTransmitter: "0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8",
uniswapV3SwapRouter: "0xE592427A0AEce92De3Edee1F18E0157C05861564",
"1inchV6Router": "0x111111125421cA6dc452d289314280a0f8842A65",
create2Factory: "0x22dAe400e0F6a330610F3060Be894ab33f9caED0",
permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
spokePoolPeripheryProxy: "0x2d5E44b66bD40267fb816c9537E026545bEbbAC8",
},
[CHAIN_IDs.OPTIMISM_SEPOLIA]: {
cctpTokenMessenger: "0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5",
Expand All @@ -206,6 +225,9 @@ export const L2_ADDRESS_MAP: { [key: number]: { [contractName: string]: string }
cctpMessageTransmitter: "0xAD09780d193884d503182aD4588450C416D6F9D4",
uniswapV3SwapRouter: "0x2626664c2603336E57B271c5C0b26F421741e481",
"1inchV6Router": "0x111111125421cA6dc452d289314280a0f8842A65",
create2Factory: "0x22dAe400e0F6a330610F3060Be894ab33f9caED0",
permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
spokePoolPeripheryProxy: "0x2d5E44b66bD40267fb816c9537E026545bEbbAC8",
},
[CHAIN_IDs.BASE_SEPOLIA]: {
cctpTokenMessenger: "0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5",
Expand All @@ -230,6 +252,16 @@ export const L2_ADDRESS_MAP: { [key: number]: { [contractName: string]: string }
scrollGasPriceOracle: "0x5300000000000000000000000000000000000002",
scrollMessenger: "0x781e90f1c8Fc4611c9b7497C3B47F99Ef6969CbC",
},
[CHAIN_IDs.WORLD_CHAIN]: {
create2Factory: "0x22dAe400e0F6a330610F3060Be894ab33f9caED0",
permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
spokePoolPeripheryProxy: "0x2d5E44b66bD40267fb816c9537E026545bEbbAC8",
},
[CHAIN_IDs.ZORA]: {
create2Factory: "0x22dAe400e0F6a330610F3060Be894ab33f9caED0",
permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
spokePoolPeripheryProxy: "0x2d5E44b66bD40267fb816c9537E026545bEbbAC8",
},
1442: {
// Custom WETH for testing because there is no "official" WETH
l2Weth: "0x3ab6C7AEb93A1CFC64AEEa8BF0f00c176EE42A2C",
Expand Down
Loading
Loading