feature: verify bridge (#525)
* add: initial attempt at contract verification * fix: hardhat config networks * fix: pass hre * test: try inside typechain folder * refactor: move verification to optics-xapps folder * add: new deploy of core and bridge contracts, successful BridgeRouter verification * fix: bad merge, compile typechain * add: new core deploy * add: generate typechain * refactor: revert old verification code in typescript folder * fix: file path, typechain gen in optics-xapps not working * fix: bridge deploy, verify bridge, beacon and proxy * refactor: create typescript/optics-deploy/verification * clean: delete console.log * fix: add ETH Helper to verification input * fix: bridge deploy after merge * delete: bridge deploy * restore: bridge deploy and solidity lint diff * add: UpgradeBeacon import * Remove unused imports & regen typescript Co-authored-by: anna-caroll <anna.s.carroll@gmail.com>buddies-main-deployment
parent
8de3d1ff0f
commit
57bef4e2b0
File diff suppressed because it is too large
Load Diff
@ -1,107 +0,0 @@ |
||||
import fs from 'fs'; |
||||
|
||||
/* |
||||
* @notice Get the list of networks included in the contract deploy at path |
||||
* @param path relative path to core system deploy |
||||
* @return list of networks deployed as strings |
||||
* */ |
||||
export function getNetworksFromDeploy(path: string): string[] { |
||||
const targetFileSuffix = `_contracts.json`; |
||||
|
||||
const deployOutputFileNames = fs |
||||
.readdirSync(path, { withFileTypes: true }) |
||||
.map((dirEntry: fs.Dirent) => dirEntry.name) |
||||
.filter((fileName: string) => fileName.includes(targetFileSuffix)); |
||||
|
||||
let chainNames: string[] = []; |
||||
for (let deployOutputFileName of deployOutputFileNames) { |
||||
const tokens: string[] = deployOutputFileName.split('_'); |
||||
const chainName: string = tokens[0]; |
||||
chainNames.push(chainName); |
||||
} |
||||
return chainNames; |
||||
} |
||||
|
||||
/* |
||||
* @notice Return the path to the folder with the greatest name |
||||
* within the folder at configPath, |
||||
* (excluding any folders within ignoreFolders) |
||||
* @param configPath relative path to top directory |
||||
* @param ignoreFolders names of folders to exclude within configPath |
||||
* @return path to folder |
||||
* */ |
||||
function getPathToLatestConfig(configPath: string, ignoreFolders: string[] = []) { |
||||
// get the names of all non-default config directories within the relative configPath
|
||||
let configFolders: string[] = fs |
||||
.readdirSync(configPath, {withFileTypes: true}) |
||||
.filter( |
||||
(dirEntry: fs.Dirent) => |
||||
dirEntry.isDirectory() && !ignoreFolders.includes(dirEntry.name), |
||||
) |
||||
.map((dirEntry: fs.Dirent) => dirEntry.name); |
||||
|
||||
// if no non-default config folders are found, return
|
||||
if (configFolders.length == 0) { |
||||
throw new Error('No config folders found'); |
||||
} |
||||
|
||||
// get path to newest generated config folder
|
||||
// (config folder names are UTC strings of the date they were generated - the greatest string is newest folder)
|
||||
const newestConfigFolder: string = configFolders.reduce((a, b) => { |
||||
return a > b ? a : b; |
||||
}); |
||||
return `${configPath}/${newestConfigFolder}`; |
||||
} |
||||
|
||||
/* |
||||
* @notice Return the path to the *most recent* bridge deploy configs |
||||
* from the *most recent* core contract deploy |
||||
* @return path to folder |
||||
* */ |
||||
export function getPathToLatestBridgeDeploy(): string { |
||||
const latestCoreDeployPath = getPathToLatestDeploy(); |
||||
return getPathToLatestConfig(latestCoreDeployPath); |
||||
} |
||||
|
||||
/* |
||||
* @notice Return the path to the *most recent* contract deploy configs |
||||
* @return path to folder |
||||
* */ |
||||
export function getPathToLatestDeploy(): string { |
||||
const configPath = '../../rust/config'; |
||||
const ignoreFolders = ["default"]; |
||||
return getPathToLatestConfig(configPath, ignoreFolders); |
||||
} |
||||
|
||||
/* |
||||
* @notice Return the JSON-parsed file specified |
||||
* for the contract deploy at path |
||||
* for the network & filetype |
||||
* Throw if the file is not found |
||||
* @param path relative path to core system deploy |
||||
* @param network target network to parse ("alfajores", "kovan"") |
||||
* @param fileSuffix target file suffix to parse ("config", "contracts", "verification") |
||||
* */ |
||||
export function parseFileFromDeploy( |
||||
path: string, |
||||
network: string, |
||||
fileSuffix: string, |
||||
): any { |
||||
const targetFileName = `${network}_${fileSuffix}.json`; |
||||
|
||||
const file = fs |
||||
.readdirSync(path, { withFileTypes: true }) |
||||
.find((dirEntry: fs.Dirent) => dirEntry.name == targetFileName); |
||||
|
||||
if (!file) { |
||||
throw new Error( |
||||
`No ${fileSuffix} files found for ${network} at ${path}/${targetFileName}`, |
||||
); |
||||
} |
||||
|
||||
const fileString: string = fs |
||||
.readFileSync(`${path}/${targetFileName}`) |
||||
.toString(); |
||||
|
||||
return JSON.parse(fileString); |
||||
} |
@ -1,81 +0,0 @@ |
||||
import { parseFileFromDeploy, getPathToLatestDeploy } from "./readDeployConfig"; |
||||
|
||||
const envError = (network: string) => |
||||
`pass --network tag to hardhat task (current network=${network})`; |
||||
|
||||
// list of networks supported by Etherscan
|
||||
const etherscanNetworks = ["mainnet", "kovan", "goerli", "ropsten", "rinkeby"]; |
||||
|
||||
/* |
||||
* Generate link to Etherscan for an address on the given network |
||||
* */ |
||||
function etherscanLink(network: string, address: string) { |
||||
const prefix = network == "mainnet" ? "" : `${network}.`; |
||||
return `https://${prefix}etherscan.io/address/${address}`; |
||||
} |
||||
|
||||
/* |
||||
* Parse the contract verification inputs |
||||
* that were output by the latest contract deploy |
||||
* for the network that hardhat is configured to |
||||
* and attempt to verify those contracts' source code on Etherscan |
||||
* */ |
||||
export async function verifyLatestCoreDeploy() { |
||||
const path = getPathToLatestDeploy(); |
||||
return verifyDeploy(path); |
||||
} |
||||
|
||||
/* |
||||
* Parse the contract verification inputs |
||||
* that were output by the given contract deploy |
||||
* for the network that hardhat is configured to |
||||
* and attempt to verify those contracts' source code on Etherscan |
||||
* */ |
||||
export async function verifyDeploy(path: string) { |
||||
// @ts-ignore
|
||||
const network = hre.network.name; |
||||
|
||||
// assert that network from .env is supported by Etherscan
|
||||
if (!etherscanNetworks.includes(network)) { |
||||
throw new Error(`Network not supported by Etherscan; ${envError(network)}`); |
||||
} |
||||
console.log(`VERIFY ${network}`); |
||||
|
||||
// get the JSON verification inputs for the given network
|
||||
// from the latest contract deploy; throw if not found
|
||||
const verificationInputs = parseFileFromDeploy(path, network, "verification",); |
||||
|
||||
// loop through each verification input for each contract in the file
|
||||
for (let verificationInput of verificationInputs) { |
||||
// attempt to verify contract on etherscan
|
||||
// (await one-by-one so that Etherscan doesn't rate limit)
|
||||
await verifyContract(network, verificationInput); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* Given one contract verification input, |
||||
* attempt to verify the contracts' source code on Etherscan |
||||
* */ |
||||
export async function verifyContract( |
||||
network: string, |
||||
verificationInput: any |
||||
) { |
||||
const { name, address, constructorArguments } = verificationInput; |
||||
try { |
||||
console.log( |
||||
` Attempt to verify ${name} - ${etherscanLink(network, address)}` |
||||
); |
||||
// @ts-ignore
|
||||
await hre.run("verify:verify", { |
||||
network, |
||||
address, |
||||
constructorArguments, |
||||
}); |
||||
console.log(` SUCCESS verifying ${name}`); |
||||
} catch (e) { |
||||
console.log(` ERROR verifying ${name}`); |
||||
console.error(e); |
||||
} |
||||
console.log("\n\n"); // add space after each attempt
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,91 @@ |
||||
const { |
||||
getPathToLatestDeployConfig, |
||||
getPathToLatestBridgeConfig, |
||||
getVerificationInputFromDeploy, |
||||
} = require('./readDeployOutput.ts'); |
||||
|
||||
const envError = (network: string) => |
||||
`pass --network tag to hardhat task (current network=${network})`; |
||||
|
||||
// list of networks supported by Etherscan
|
||||
const etherscanNetworks = ['mainnet', 'kovan', 'goerli', 'ropsten', 'rinkeby']; |
||||
|
||||
/* |
||||
* Generate link to Etherscan for an address on the given network |
||||
* */ |
||||
function etherscanLink(network: string, address: string) { |
||||
const prefix = network == 'mainnet' ? '' : `${network}.`; |
||||
return `https://${prefix}etherscan.io/address/${address}`; |
||||
} |
||||
|
||||
/* |
||||
* Parse the contract verification inputs |
||||
* that were output by the latest contract deploy |
||||
* for the network that hardhat is configured to |
||||
* and attempt to verify those contracts' source code on Etherscan |
||||
* */ |
||||
export async function verifyLatestBridgeDeploy(hre: any) { |
||||
const path = getPathToLatestBridgeConfig(); |
||||
return verifyDeploy(path, hre); |
||||
} |
||||
|
||||
/* |
||||
* Parse the contract verification inputs |
||||
* that were output by the latest contract deploy |
||||
* for the network that hardhat is configured to |
||||
* and attempt to verify those contracts' source code on Etherscan |
||||
* */ |
||||
export async function verifyLatestCoreDeploy(hre: any) { |
||||
const path = getPathToLatestDeployConfig(); |
||||
return verifyDeploy(path, hre); |
||||
} |
||||
|
||||
/* |
||||
* Parse the contract verification inputs |
||||
* that were output by the given contract deploy |
||||
* for the network that hardhat is configured to |
||||
* and attempt to verify those contracts' source code on Etherscan |
||||
* */ |
||||
async function verifyDeploy(path: string, hre: any) { |
||||
const network = hre.network.name; |
||||
|
||||
// assert that network from .env is supported by Etherscan
|
||||
if (!etherscanNetworks.includes(network)) { |
||||
throw new Error(`Network not supported by Etherscan; ${envError(network)}`); |
||||
} |
||||
console.log(`VERIFY ${network}`); |
||||
|
||||
// get the JSON verification inputs for the given network
|
||||
// from the latest contract deploy; throw if not found
|
||||
const verificationInputs = getVerificationInputFromDeploy(path, network); |
||||
|
||||
// loop through each verification input for each contract in the file
|
||||
for (let verificationInput of verificationInputs) { |
||||
// attempt to verify contract on etherscan
|
||||
// (await one-by-one so that Etherscan doesn't rate limit)
|
||||
await verifyContract(network, verificationInput, hre); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* Given one contract verification input, |
||||
* attempt to verify the contracts' source code on Etherscan |
||||
* */ |
||||
async function verifyContract(network: string, verificationInput: any, hre: any) { |
||||
const { name, address, constructorArguments } = verificationInput; |
||||
try { |
||||
console.log( |
||||
` Attempt to verify ${name} - ${etherscanLink(network, address)}`, |
||||
); |
||||
await hre.run('verify:verify', { |
||||
network, |
||||
address, |
||||
constructorArguments, |
||||
}); |
||||
console.log(` SUCCESS verifying ${name}`); |
||||
} catch (e) { |
||||
console.log(` ERROR verifying ${name}`); |
||||
console.error(e); |
||||
} |
||||
console.log('\n\n'); // add space after each attempt
|
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue