From 578b590c053afbad0fbb40bb18aa3726e100499c Mon Sep 17 00:00:00 2001 From: Akash Gianchandani Date: Thu, 16 May 2024 18:13:45 +0530 Subject: [PATCH] feat(eth-multisig-v4): add script to deploy v1 forwarder COIN-685 This PR adds private key and a script for v1 forwarder contract deployment. --- .github/workflows/deploy_and_release.yml | 3 + .github/workflows/push.yml | 1 + hardhat.config.ts | 4 +- package.json | 2 +- scripts/deployV1Forwarder.ts | 93 ++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 scripts/deployV1Forwarder.ts diff --git a/.github/workflows/deploy_and_release.yml b/.github/workflows/deploy_and_release.yml index ccaad05..98fa160 100644 --- a/.github/workflows/deploy_and_release.yml +++ b/.github/workflows/deploy_and_release.yml @@ -19,6 +19,7 @@ jobs: MAINNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT: ${{ secrets.MAINNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT }} TESTNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT: ${{ secrets.TESTNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT }} PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT: ${{ secrets.PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT }} + PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT_BACKUP: ${{ secrets.PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT_BACKUP }} QUICKNODE_ETH_MAINNET_API_KEY: ${{ secrets.QUICKNODE_ETH_MAINNET_API_KEY }} QUICKNODE_ETH_HOLESKY_API_KEY: ${{ secrets.QUICKNODE_ETH_HOLESKY_API_KEY }} QUICKNODE_ARBITRUM_SEPOLIA_API_KEY: ${{ secrets.QUICKNODE_ARBITRUM_SEPOLIA_API_KEY }} @@ -68,6 +69,7 @@ jobs: MAINNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT: ${{ secrets.MAINNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT }} TESTNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT: ${{ secrets.TESTNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT }} PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT: ${{ secrets.PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT }} + PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT_BACKUP: ${{ secrets.PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT_BACKUP }} QUICKNODE_ETH_HOLESKY_API_KEY: ${{ secrets.QUICKNODE_ETH_HOLESKY_API_KEY }} QUICKNODE_ARBITRUM_SEPOLIA_API_KEY: ${{ secrets.QUICKNODE_ARBITRUM_SEPOLIA_API_KEY }} QUICKNODE_OPTIMISM_SEPOLIA_API_KEY: ${{ secrets.QUICKNODE_OPTIMISM_SEPOLIA_API_KEY }} @@ -125,6 +127,7 @@ jobs: MAINNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT: ${{ secrets.MAINNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT }} TESTNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT: ${{ secrets.TESTNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT }} PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT: ${{ secrets.PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT }} + PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT_BACKUP: ${{ secrets.PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT_BACKUP }} QUICKNODE_ETH_MAINNET_API_KEY: ${{ secrets.QUICKNODE_ETH_MAINNET_API_KEY }} ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }} ALCHEMY_POLYGON_API_KEY: ${{ secrets.ALCHEMY_POLYGON_API_KEY }} diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index dbb87e4..8f43006 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -27,6 +27,7 @@ jobs: MAINNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT: ${{ secrets.MAINNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT }} TESTNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT: ${{ secrets.TESTNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT }} PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT: ${{ secrets.PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT }} + PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT_BACKUP: ${{ secrets.PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT_BACKUP }} QUICKNODE_ETH_MAINNET_API_KEY: ${{ secrets.QUICKNODE_ETH_MAINNET_API_KEY }} QUICKNODE_ETH_HOLESKY_API_KEY: ${{ secrets.QUICKNODE_ETH_HOLESKY_API_KEY }} QUICKNODE_ARBITRUM_SEPOLIA_API_KEY: ${{ secrets.QUICKNODE_ARBITRUM_SEPOLIA_API_KEY }} diff --git a/hardhat.config.ts b/hardhat.config.ts index 130dd8d..86557ac 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -14,7 +14,7 @@ const { TESTNET_PRIVATE_KEY_FOR_CONTRACT_DEPLOYMENT, PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT, QUICKNODE_ETH_MAINNET_API_KEY, - QUICKNODE_ETH_HOLESKY_API_KEY, + PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT_BACKUP, QUICKNODE_ARBITRUM_SEPOLIA_API_KEY, QUICKNODE_OPTIMISM_SEPOLIA_API_KEY, QUICKNODE_ARBITRUM_ONE_API_KEY, @@ -70,7 +70,7 @@ const config: HardhatUserConfig = { }, hteth: { url: `https://rpc.holesky.ethpandaops.io/`, - accounts: [`${PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT}`] + accounts: [`${PRIVATE_KEY_FOR_V4_CONTRACT_DEPLOYMENT_BACKUP}`] }, matic: { url: `https://polygon-mainnet.g.alchemyapi.io/v2/${ALCHEMY_POLYGON_API_KEY}`, diff --git a/package.json b/package.json index 53fac50..f2fd0d2 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ }, "scripts": { "deploy-prod": "hardhat run scripts/deploy.ts --network", - "deploy-test": "hardhat run scripts/deploy.ts --network", + "deploy-test": "hardhat run scripts/deployV1Forwarder.ts --network", "test": "hardhat test", "coverage": "hardhat coverage", "solhint": "./node_modules/.bin/solhint --fix 'contracts/**/*.sol'", diff --git a/scripts/deployV1Forwarder.ts b/scripts/deployV1Forwarder.ts new file mode 100644 index 0000000..1c5c76f --- /dev/null +++ b/scripts/deployV1Forwarder.ts @@ -0,0 +1,93 @@ +import { use } from 'chai'; +import { ethers } from 'hardhat'; +const hre = require('hardhat'); +const fs = require('fs'); + +async function main() { + const output = { + forwarderImplementation: '', + forwarderFactory: '' + }; + + const feeData = await ethers.provider.getFeeData(); + const gasParams = { + gasPrice: feeData.gasPrice + }; + + const [deployer] = await ethers.getSigners(); + + let forwarderContractName = 'Forwarder'; + let forwarderFactoryContractName = 'ForwarderFactory'; + + const Forwarder = await ethers.getContractFactory(forwarderContractName); + const forwarder = await Forwarder.deploy(gasParams); + await forwarder.deployed(); + output.forwarderImplementation = forwarder.address; + console.log(`${forwarderContractName} deployed at ` + forwarder.address); + + const ForwarderFactory = await ethers.getContractFactory( + forwarderFactoryContractName + ); + const forwarderFactory = await ForwarderFactory.deploy( + forwarder.address, + gasParams + ); + await forwarderFactory.deployed(); + output.forwarderFactory = forwarderFactory.address; + console.log( + `${forwarderFactoryContractName} deployed at ` + forwarderFactory.address + ); + + fs.writeFileSync('output.json', JSON.stringify(output)); + + // Wait 5 minutes. It takes some time for the etherscan backend to index the transaction and store the contract. + console.log('Waiting for 5 minutes before verifying.....'); + await new Promise((r) => setTimeout(r, 1000 * 300)); + + // We have to wait for a minimum of 10 block confirmations before we can call the etherscan api to verify + await forwarder.deployTransaction.wait(10); + await forwarderFactory.deployTransaction.wait(10); + + console.log('Done waiting, verifying'); + await verifyContract(forwarderContractName, forwarder.address, []); + await verifyContract(forwarderFactoryContractName, forwarderFactory.address, [ + forwarder.address + ]); + console.log('Contracts verified'); +} + +async function verifyContract( + contractName: string, + contractAddress: string, + constructorArguments: string[], + contract?: string +) { + try { + const verifyContractArgs: { + address: string; + constructorArguments: string[]; + contract?: string; + } = { + address: contractAddress, + constructorArguments: constructorArguments + }; + + if (contract) { + verifyContractArgs.contract = contract; + } + + await hre.run('verify:verify', verifyContractArgs); + } catch (e) { + // @ts-ignore + // We get a failure API response if the source code has already been uploaded, don't throw in this case. + if (!e.message.includes('Reason: Already Verified')) { + throw e; + } + } + console.log(`Verified ${contractName} on Etherscan!`); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +});