diff --git a/.gitignore b/.gitignore index e11008ac..5344343c 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,5 @@ typings/ .env .idea .vscode -**/.DS_Store \ No newline at end of file +**/.DS_Store +examples/contract-verification/.openzeppelin/ diff --git a/.prettierrc.json b/.prettierrc.json index 0bc4e0b0..6c40be31 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,4 +1,5 @@ { "proseWrap": "never", - "printWidth": 120 -} \ No newline at end of file + "printWidth": 80, + "trailingComma": "all" +} diff --git a/config/eslint/eslintrc.js b/config/eslint/eslintrc.js index 4a0bb139..1a6f6aae 100644 --- a/config/eslint/eslintrc.js +++ b/config/eslint/eslintrc.js @@ -9,8 +9,16 @@ module.exports = { plugins: [ "eslint-plugin-import", "@typescript-eslint", + "prettier", ], rules: { + "prettier/prettier": [ + "error", + { + "printWidth": 80, + "trailingComma": "all" + } + ], "@typescript-eslint/adjacent-overload-signatures": "error", "@typescript-eslint/array-type": [ "error", @@ -213,4 +221,4 @@ module.exports = { "use-isnan": "error", "no-restricted-imports": ["error"], }, - }; \ No newline at end of file + }; diff --git a/examples/contract-verification/hardhat.config.ts b/examples/contract-verification/hardhat.config.ts index 14dff75d..f4f13127 100644 --- a/examples/contract-verification/hardhat.config.ts +++ b/examples/contract-verification/hardhat.config.ts @@ -4,13 +4,22 @@ import "@nomicfoundation/hardhat-ethers"; import { HardhatUserConfig } from "hardhat/config"; import * as dotenv from "dotenv"; -const { TENDERLY_PRIVATE_VERIFICATION, TENDERLY_AUTOMATIC_VERIFICATION } = process.env; +const { TENDERLY_PRIVATE_VERIFICATION, TENDERLY_AUTOMATIC_VERIFICATION } = + process.env; const privateVerification = TENDERLY_PRIVATE_VERIFICATION === "true"; const automaticVerifications = TENDERLY_AUTOMATIC_VERIFICATION === "true"; -console.log("Using private verification? ", privateVerification, TENDERLY_PRIVATE_VERIFICATION); -console.log("Using automatic verification? ", automaticVerifications, TENDERLY_AUTOMATIC_VERIFICATION); +console.log( + "Using private verification? ", + privateVerification, + TENDERLY_PRIVATE_VERIFICATION, +); +console.log( + "Using automatic verification? ", + automaticVerifications, + TENDERLY_AUTOMATIC_VERIFICATION, +); tdly.setup({ automaticVerifications }); @@ -19,13 +28,16 @@ dotenv.config(); const config: HardhatUserConfig = { solidity: "0.8.17", networks: { - my_tenderly_fork_1: { // or any other name + my_tenderly_fork_1: { + // or any other name url: `${process.env.TENDERLY_FORK_RPC_URL ?? ""}`, }, - my_tenderly_devnet_1: { // or any other name + my_tenderly_devnet_1: { + // or any other name url: `${process.env.TENDERLY_DEVNET_RPC_URL_1 ?? ""}`, }, - my_tenderly_devnet_2: { // or any other name + my_tenderly_devnet_2: { + // or any other name url: `${process.env.TENDERLY_DEVNET_RPC_URL_2 ?? ""}`, }, sepolia: { @@ -33,7 +45,6 @@ const config: HardhatUserConfig = { accounts: [process.env.SEPOLIA_PRIVATE_KEY ?? ""], }, }, - tenderly: { project: process.env.TENDERLY_PROJECT ?? "", username: process.env.TENDERLY_USERNAME ?? "", diff --git a/examples/contract-verification/scripts/calculator/manual-advanced-fork.ts b/examples/contract-verification/scripts/calculator/manual-advanced-fork.ts index 770b70a8..38430a39 100644 --- a/examples/contract-verification/scripts/calculator/manual-advanced-fork.ts +++ b/examples/contract-verification/scripts/calculator/manual-advanced-fork.ts @@ -5,7 +5,8 @@ import { HttpNetworkConfig } from "hardhat/types"; import { deployCalculator, deployMaths } from "./maths-deployment-ethers"; export async function main() { - const forkID = `${(network.config as HttpNetworkConfig).url}`.split("/").pop() ?? ""; + const forkID = + `${(network.config as HttpNetworkConfig).url}`.split("/").pop() ?? ""; // 📐 Maths const mathsAddress = await deployMaths(); @@ -26,15 +27,24 @@ export async function main() { sources: { "contracts/Calculator.sol": { name: "Calculator", - code: readFileSync("contracts/Calculator.sol", "utf-8").toString(), + code: readFileSync( + "contracts/Calculator.sol", + "utf-8", + ).toString(), }, "hardhat/console.sol": { name: "console", - code: readFileSync("node_modules/hardhat/console.sol", "utf-8").toString(), + code: readFileSync( + "node_modules/hardhat/console.sol", + "utf-8", + ).toString(), }, "contracts/libraries/Maths.sol": { name: "Maths", - code: readFileSync("contracts/libraries/Maths.sol", "utf-8").toString(), + code: readFileSync( + "contracts/libraries/Maths.sol", + "utf-8", + ).toString(), }, }, // solidity format compiler with a little modification at libraries param @@ -66,7 +76,7 @@ export async function main() { }, process.env.TENDERLY_PROJECT ?? "", process.env.TENDERLY_USERNAME ?? "", - forkID + forkID, ); } diff --git a/examples/contract-verification/scripts/calculator/manual-advanced.ts b/examples/contract-verification/scripts/calculator/manual-advanced.ts index 5758265e..5e8f1b87 100644 --- a/examples/contract-verification/scripts/calculator/manual-advanced.ts +++ b/examples/contract-verification/scripts/calculator/manual-advanced.ts @@ -30,11 +30,17 @@ export async function main() { }, "hardhat/console.sol": { name: "console", - code: readFileSync("node_modules/hardhat/console.sol", "utf-8").toString(), + code: readFileSync( + "node_modules/hardhat/console.sol", + "utf-8", + ).toString(), }, "contracts/libraries/Maths.sol": { name: "Maths", - code: readFileSync("contracts/libraries/Maths.sol", "utf-8").toString(), + code: readFileSync( + "contracts/libraries/Maths.sol", + "utf-8", + ).toString(), }, }, // solidity format compiler with a little modification at libraries param diff --git a/examples/contract-verification/scripts/calculator/maths-deployment-ethers.ts b/examples/contract-verification/scripts/calculator/maths-deployment-ethers.ts index 78a20dd7..2370633d 100644 --- a/examples/contract-verification/scripts/calculator/maths-deployment-ethers.ts +++ b/examples/contract-verification/scripts/calculator/maths-deployment-ethers.ts @@ -20,6 +20,9 @@ export async function deployCalculator(mathsAddress: string) { }); calculator = await calculator.waitForDeployment(); - console.log("🧮[ethers] {Calculator} deployed to", await calculator.getAddress()); + console.log( + "🧮[ethers] {Calculator} deployed to", + await calculator.getAddress(), + ); return await calculator.getAddress(); } diff --git a/examples/contract-verification/scripts/greeter/manual-advanced-fork.ts b/examples/contract-verification/scripts/greeter/manual-advanced-fork.ts index f7cb9df3..ec16b622 100644 --- a/examples/contract-verification/scripts/greeter/manual-advanced-fork.ts +++ b/examples/contract-verification/scripts/greeter/manual-advanced-fork.ts @@ -3,11 +3,14 @@ import { network, ethers, tenderly } from "hardhat"; import { HttpNetworkConfig } from "hardhat/types"; export async function main() { - const forkID = `${(network.config as HttpNetworkConfig).url}`.split("/").pop() ?? ""; + const forkID = + `${(network.config as HttpNetworkConfig).url}`.split("/").pop() ?? ""; console.log("🖖🏽[ethers] Deploying and Verifying Greeter in Tenderly"); - let greeter = await ethers.deployContract("Greeter", ["Hello, Manual Hardhat on Fork !"]); + let greeter = await ethers.deployContract("Greeter", [ + "Hello, Manual Hardhat on Fork !", + ]); greeter = await greeter.waitForDeployment(); const greeterAddress = await greeter.getAddress(); @@ -25,7 +28,10 @@ export async function main() { }, "hardhat/console.sol": { name: "console", - code: readFileSync("node_modules/hardhat/console.sol", "utf-8").toString(), + code: readFileSync( + "node_modules/hardhat/console.sol", + "utf-8", + ).toString(), }, }, // solidity format compiler with a little modification at libraries param @@ -48,7 +54,7 @@ export async function main() { }, process.env.TENDERLY_PROJECT ?? "", process.env.TENDERLY_USERNAME ?? "", - forkID + forkID, ); } diff --git a/examples/contract-verification/scripts/greeter/manual-advanced.ts b/examples/contract-verification/scripts/greeter/manual-advanced.ts index f0603427..36f24459 100644 --- a/examples/contract-verification/scripts/greeter/manual-advanced.ts +++ b/examples/contract-verification/scripts/greeter/manual-advanced.ts @@ -5,7 +5,9 @@ import { ethers, tenderly } from "hardhat"; export async function main() { console.log("🖖🏽[ethers] Deploying and Verifying Greeter in Tenderly"); // deploy stuff but later pretend it's been deployed ages ago on Ropsten. - let greeter = await ethers.deployContract("Greeter", ["Hello, Manual Hardhat!"]); + let greeter = await ethers.deployContract("Greeter", [ + "Hello, Manual Hardhat!", + ]); greeter = await greeter.waitForDeployment(); const greeterAddress = await greeter.getAddress(); @@ -26,7 +28,10 @@ export async function main() { }, "hardhat/console.sol": { name: "console", - code: readFileSync("node_modules/hardhat/console.sol", "utf-8").toString(), + code: readFileSync( + "node_modules/hardhat/console.sol", + "utf-8", + ).toString(), }, }, // solidity format compiler with a little modification at libraries param diff --git a/examples/contract-verification/scripts/greeter/manual-simple.ts b/examples/contract-verification/scripts/greeter/manual-simple.ts index 6d521d44..b4f6314b 100644 --- a/examples/contract-verification/scripts/greeter/manual-simple.ts +++ b/examples/contract-verification/scripts/greeter/manual-simple.ts @@ -4,7 +4,9 @@ import { ethers, tenderly } from "hardhat"; async function main() { console.log("🖖🏽[ethers] Deploying and Verifying Greeter in Tenderly"); - let greeter = await ethers.deployContract("Greeter", ["Hello, Manual Hardhat!"]); + let greeter = await ethers.deployContract("Greeter", [ + "Hello, Manual Hardhat!", + ]); greeter = await greeter.waitForDeployment(); const address = await greeter.getAddress(); diff --git a/package.json b/package.json index 653f8403..3a0e5589 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build": "yarn --cwd packages/tenderly-core run build && yarn --cwd packages/tenderly-hardhat run build", "lint:fix": "wsrun --exclude-missing --stages lint:fix && yarn prettier --write", "prettier": "prettier *.md \"{docs,.github}/**/*.{md,yml}\"", - "format": "prettier --write \"**/*.{ts,tsx,md}\"", + "format": "prettier --write \"**/*.{ts,tsx}\"", "changeset": "changeset", "release": "changeset publish", "version-packages": "changeset version" diff --git a/packages/tenderly-core/src/internal/cli/commands/LoginCommand.ts b/packages/tenderly-core/src/internal/cli/commands/LoginCommand.ts index 0bc773cb..f39933c2 100644 --- a/packages/tenderly-core/src/internal/cli/commands/LoginCommand.ts +++ b/packages/tenderly-core/src/internal/cli/commands/LoginCommand.ts @@ -5,37 +5,50 @@ import commander from "commander"; import { logger } from "../../../utils/logger"; import { isAccessTokenSet, setAccessToken } from "../../../utils/config"; -import { TENDERLY_API_BASE_URL, TENDERLY_DASHBOARD_BASE_URL } from "../../../common/constants"; +import { + TENDERLY_API_BASE_URL, + TENDERLY_DASHBOARD_BASE_URL, +} from "../../../common/constants"; -export const LoginCommand = new commander.Command("login").description("login to Tenderly").action(async () => { - logger.info("Trying to login to Tenderly."); +export const LoginCommand = new commander.Command("login") + .description("login to Tenderly") + .action(async () => { + logger.info("Trying to login to Tenderly."); - if (isAccessTokenSet()) { - logger.debug("Access token is already set. Checking if access token overwrite is needed."); - const response = await prompts({ - type: "confirm", - name: "overwrite", - message: "Access token already set. Would you like to overwrite it?", - }); - if (!response.overwrite) { - logger.debug("Access token overwrite skipped. Trying to login with the existing token."); - return; + if (isAccessTokenSet()) { + logger.debug( + "Access token is already set. Checking if access token overwrite is needed.", + ); + const response = await prompts({ + type: "confirm", + name: "overwrite", + message: "Access token already set. Would you like to overwrite it?", + }); + if (!response.overwrite) { + logger.debug( + "Access token overwrite skipped. Trying to login with the existing token.", + ); + return; + } } - } - logger.info("Access token not set."); - const accessToken = await promptAccessToken(); + logger.info("Access token not set."); + const accessToken = await promptAccessToken(); - logger.debug("Access token accepted. Trying to log in."); - setAccessToken(accessToken); + logger.debug("Access token accepted. Trying to log in."); + setAccessToken(accessToken); - console.log("Successfully logged in to Tenderly."); - logger.info("Successfully logged in to Tenderly."); -}); + console.log("Successfully logged in to Tenderly."); + logger.info("Successfully logged in to Tenderly."); + }); async function promptAccessToken(): Promise { - console.log(`Redirecting to ${TENDERLY_DASHBOARD_BASE_URL}/account/authorization`); - logger.debug(`Redirecting to ${TENDERLY_DASHBOARD_BASE_URL}/account/authorization`); + console.log( + `Redirecting to ${TENDERLY_DASHBOARD_BASE_URL}/account/authorization`, + ); + logger.debug( + `Redirecting to ${TENDERLY_DASHBOARD_BASE_URL}/account/authorization`, + ); await open(`${TENDERLY_DASHBOARD_BASE_URL}/account/authorization`); logger.info("Requesting access token."); diff --git a/packages/tenderly-core/src/internal/cli/commands/NetworksCommand.ts b/packages/tenderly-core/src/internal/cli/commands/NetworksCommand.ts index 4562a1cd..6a95471d 100644 --- a/packages/tenderly-core/src/internal/cli/commands/NetworksCommand.ts +++ b/packages/tenderly-core/src/internal/cli/commands/NetworksCommand.ts @@ -24,7 +24,8 @@ export const NetworksCommand = new commander.Command("networks") const filteredNetworks = networks.filter(isNotExcluded); filteredNetworks.sort((a, b) => a.sort_order - b.sort_order); - const logCompliantNetworks = convertToLogCompliantNetworks(filteredNetworks); + const logCompliantNetworks = + convertToLogCompliantNetworks(filteredNetworks); logger.silly("Obtained filtered public networks:", logCompliantNetworks); const table = new Table({ @@ -36,13 +37,15 @@ export const NetworksCommand = new commander.Command("networks") ...(await Promise.all( filteredNetworks.map(async (network) => { if (verbose) { - const blockNumber = await tenderlyService.getLatestBlockNumber(network.ethereum_network_id); + const blockNumber = await tenderlyService.getLatestBlockNumber( + network.ethereum_network_id, + ); return [network.ethereum_network_id, network.name, blockNumber]; } else { return [network.ethereum_network_id, network.name]; } - }) - )) + }), + )), ); logger.silly("Networks table:", table); @@ -50,5 +53,8 @@ export const NetworksCommand = new commander.Command("networks") }); function isNotExcluded(element: TenderlyNetwork): boolean { - return element.metadata.exclude_from_listing === undefined || element.metadata.exclude_from_listing === false; + return ( + element.metadata.exclude_from_listing === undefined || + element.metadata.exclude_from_listing === false + ); } diff --git a/packages/tenderly-core/src/internal/core/services/TenderlyApiService.ts b/packages/tenderly-core/src/internal/core/services/TenderlyApiService.ts index f966e00d..7ae99633 100644 --- a/packages/tenderly-core/src/internal/core/services/TenderlyApiService.ts +++ b/packages/tenderly-core/src/internal/core/services/TenderlyApiService.ts @@ -2,32 +2,37 @@ import * as axios from "axios"; import { logger } from "../../../utils/logger"; import { getConfig, isAccessTokenSet } from "../../../utils/config"; -import { TENDERLY_API_BASE_URL, TENDERLY_JSON_RPC_BASE_URL } from "../../../common/constants"; -import {HARDHAT_TENDERLY_VERSION} from "./hardhat-tenderly-version"; +import { + TENDERLY_API_BASE_URL, + TENDERLY_JSON_RPC_BASE_URL, +} from "../../../common/constants"; +import { HARDHAT_TENDERLY_VERSION } from "./hardhat-tenderly-version"; export class TenderlyApiService { - public static configureInstance(providedAccessKey?: string): axios.AxiosInstance { + public static configureInstance( + providedAccessKey?: string, + ): axios.AxiosInstance { logger.debug("Configuring instance."); - let accessKey: string + let accessKey: string; if (!!providedAccessKey) { - accessKey = providedAccessKey + accessKey = providedAccessKey; } else { const tdlyConfig = getConfig(); - accessKey = tdlyConfig.access_key + accessKey = tdlyConfig.access_key; } const params = { baseURL: TENDERLY_API_BASE_URL, - headers: { + headers: { "x-access-key": accessKey, - "x-user-agent": `@tenderly/hardhat-tenderly/${HARDHAT_TENDERLY_VERSION}` + "x-user-agent": `@tenderly/hardhat-tenderly/${HARDHAT_TENDERLY_VERSION}`, }, }; logger.debug("Configured instance with parameters:", { baseURL: TENDERLY_API_BASE_URL, access_key: - accessKey !== undefined && accessKey !== null && accessKey !== "" + accessKey !== undefined && accessKey !== null && accessKey !== "" ? "super secret access_key is set in 'access_key' field" : "undefined or null or empty string", }); @@ -58,7 +63,9 @@ export class TenderlyApiService { logger.debug("Configured tenderly rpc instance with parameters:", { baseURL: TENDERLY_JSON_RPC_BASE_URL, access_key: - tdlyConfig.access_key !== undefined && tdlyConfig.access_key !== null && tdlyConfig.access_key !== "" + tdlyConfig.access_key !== undefined && + tdlyConfig.access_key !== null && + tdlyConfig.access_key !== "" ? "super secret access_key is set in 'access_key' field" : "undefined or null or empty string", }); diff --git a/packages/tenderly-core/src/internal/core/services/TenderlyService.ts b/packages/tenderly-core/src/internal/core/services/TenderlyService.ts index 90f3ea40..4a73c1e4 100644 --- a/packages/tenderly-core/src/internal/core/services/TenderlyService.ts +++ b/packages/tenderly-core/src/internal/core/services/TenderlyService.ts @@ -1,4 +1,7 @@ -import { CHAIN_ID_NETWORK_NAME_MAP, TENDERLY_DASHBOARD_BASE_URL } from "../../../common/constants"; +import { + CHAIN_ID_NETWORK_NAME_MAP, + TENDERLY_DASHBOARD_BASE_URL, +} from "../../../common/constants"; import { ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG, API_ADD_CONTRACT_REQUEST_ERR_MSG, @@ -49,7 +52,9 @@ export class TenderlyService { try { const res = await tenderlyApi.get("/api/v1/public-networks"); if (res.data === undefined || res.data === null) { - logger.error("There was an error while obtaining public networks from Tenderly. Obtained response is invalid."); + logger.error( + "There was an error while obtaining public networks from Tenderly. Obtained response is invalid.", + ); return []; } const logCompliantNetworks = convertToLogCompliantNetworks(res.data); @@ -59,7 +64,9 @@ export class TenderlyService { } catch (err) { const logCompliantApiErr = convertToLogCompliantApiError(err); logger.error(logCompliantApiErr); - console.log(`Error in ${this.pluginName}: ${NETWORK_FETCH_FAILED_ERR_MSG}`); + console.log( + `Error in ${this.pluginName}: ${NETWORK_FETCH_FAILED_ERR_MSG}`, + ); } return []; } @@ -73,10 +80,12 @@ export class TenderlyService { } try { - const res = await tenderlyApi.get(`/api/v1/network/${networkId}/block-number`); + const res = await tenderlyApi.get( + `/api/v1/network/${networkId}/block-number`, + ); if (res.data === undefined || res.data === null) { logger.error( - "There was an error while obtaining latest block number from Tenderly. Obtained response is invalid." + "There was an error while obtaining latest block number from Tenderly. Obtained response is invalid.", ); return null; } @@ -86,12 +95,16 @@ export class TenderlyService { } catch (err) { const logCompliantApiErr = convertToLogCompliantApiError(err); logger.error(logCompliantApiErr); - logger.error(`Error in ${this.pluginName}: ${LATEST_BLOCK_NUMBER_FETCH_FAILED_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${LATEST_BLOCK_NUMBER_FETCH_FAILED_ERR_MSG}`, + ); } return null; } - public async verifyContracts(request: TenderlyContractUploadRequest): Promise { + public async verifyContracts( + request: TenderlyContractUploadRequest, + ): Promise { logger.debug("Verifying contracts publicly."); let tenderlyApi = TenderlyApiService.configureAnonymousInstance(); @@ -105,24 +118,34 @@ export class TenderlyService { return; } - const res = await tenderlyApi.post("/api/v1/public/verify-contracts", { ...request }); + const res = await tenderlyApi.post("/api/v1/public/verify-contracts", { + ...request, + }); if (res.data === undefined || res.data === null) { logger.error( - "There was an error while publicly verifying contracts on Tenderly. Obtained response is invalid." + "There was an error while publicly verifying contracts on Tenderly. Obtained response is invalid.", ); return; } - const logCompliantVerificationResponse = convertToLogCompliantVerificationResponse(res.data); + const logCompliantVerificationResponse = + convertToLogCompliantVerificationResponse(res.data); logger.trace("Verification response:", logCompliantVerificationResponse); const responseData: ContractResponse = res.data; if (responseData.bytecode_mismatch_errors !== null) { - logger.error(`Error in ${this.pluginName}: ${BYTECODE_MISMATCH_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${BYTECODE_MISMATCH_ERR_MSG}`, + ); return; } - if (responseData.contracts === undefined || responseData.contracts === null) { - logger.error("There was an error during public verification. There are no returned contracts."); + if ( + responseData.contracts === undefined || + responseData.contracts === null + ) { + logger.error( + "There was an error during public verification. There are no returned contracts.", + ); return; } @@ -132,7 +155,10 @@ export class TenderlyService { addresses += `${cont.contractName}, `; } - logger.error(`Error in ${this.pluginName}: ${NO_NEW_CONTRACTS_VERIFIED_ERR_MSG}`, addresses); + logger.error( + `Error in ${this.pluginName}: ${NO_NEW_CONTRACTS_VERIFIED_ERR_MSG}`, + addresses, + ); return; } @@ -143,42 +169,56 @@ export class TenderlyService { const contractLink = `${TENDERLY_DASHBOARD_BASE_URL}/contract/${ CHAIN_ID_NETWORK_NAME_MAP[contract.network_id] }/${contract.address}`; - console.log(`Contract ${contract.address} verified. You can view the contract at ${contractLink}`); + console.log( + `Contract ${contract.address} verified. You can view the contract at ${contractLink}`, + ); } console.groupEnd(); } catch (err) { const logCompliantApiError = convertToLogCompliantApiError(err); logger.error(logCompliantApiError); - logger.error(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`, + ); } } public async pushContracts( request: TenderlyContractUploadRequest, tenderlyProject: string, - username: string + username: string, ): Promise { logger.debug("Pushing contracts onto Tenderly."); if (!TenderlyApiService.isAuthenticated()) { - logger.error(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`, + ); return; } const tenderlyApi = TenderlyApiService.configureInstance(); try { - const res = await tenderlyApi.post(`/api/v1/account/${username}/project/${tenderlyProject}/contracts`, { - ...request, - }); + const res = await tenderlyApi.post( + `/api/v1/account/${username}/project/${tenderlyProject}/contracts`, + { + ...request, + }, + ); if (res.data === undefined || res.data === null) { - logger.error("There was an error while pushing contracts to Tenderly. Obtained response is invalid."); + logger.error( + "There was an error while pushing contracts to Tenderly. Obtained response is invalid.", + ); return; } - const logCompliantVerificationResponse = convertToLogCompliantVerificationResponse(res.data); + const logCompliantVerificationResponse = + convertToLogCompliantVerificationResponse(res.data); logger.trace("Verification response:", logCompliantVerificationResponse); const responseData: ContractResponse = res.data; if (responseData.bytecode_mismatch_errors !== null) { - logger.error(`Error in ${this.pluginName}: ${BYTECODE_MISMATCH_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${BYTECODE_MISMATCH_ERR_MSG}`, + ); return; } @@ -188,23 +228,32 @@ export class TenderlyService { addresses += `${cont.contractName}, `; } - logger.error(`Error in ${this.pluginName}: ${NO_NEW_CONTRACTS_VERIFIED_ERR_MSG}`, addresses); + logger.error( + `Error in ${this.pluginName}: ${NO_NEW_CONTRACTS_VERIFIED_ERR_MSG}`, + addresses, + ); return; } const dashLink = `${TENDERLY_DASHBOARD_BASE_URL}/${username}/${tenderlyProject}/contracts`; console.log( - `Successfully privately verified Smart Contracts for project ${tenderlyProject}. You can view your contracts at ${dashLink}` + `Successfully privately verified Smart Contracts for project ${tenderlyProject}. You can view your contracts at ${dashLink}`, ); } catch (err) { const logCompliantApiError = convertToLogCompliantApiError(err); logger.error(logCompliantApiError); - logger.error(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`, + ); } } - public async verifyContractsMultiCompiler(request: TenderlyVerifyContractsRequest): Promise { - logger.debug("Publicly verifying contracts on tenderly. (Multi compiler version)"); + public async verifyContractsMultiCompiler( + request: TenderlyVerifyContractsRequest, + ): Promise { + logger.debug( + "Publicly verifying contracts on tenderly. (Multi compiler version)", + ); let tenderlyApi = TenderlyApiService.configureAnonymousInstance(); if (TenderlyApiService.isAuthenticated()) { @@ -217,24 +266,32 @@ export class TenderlyService { return; } - const res = await tenderlyApi.post("/api/v1/public/contracts/verify", { ...request }); + const res = await tenderlyApi.post("/api/v1/public/contracts/verify", { + ...request, + }); if (res.data === undefined || res.data === null) { logger.error( - "There was an error while publicly verifying contracts on Tenderly. Obtained response is invalid." + "There was an error while publicly verifying contracts on Tenderly. Obtained response is invalid.", ); return; } const response = convertToLogCompliantVerificationResponse(res.data); logger.trace("Verification response:", response); - if (response.compilation_errors !== undefined && response.compilation_errors !== null) { - logger.error("There have been compilation errors while verifying contracts.", response.compilation_errors); + if ( + response.compilation_errors !== undefined && + response.compilation_errors !== null + ) { + logger.error( + "There have been compilation errors while verifying contracts.", + response.compilation_errors, + ); return; } if (response.results === undefined || response.results === null) { logger.error( - "There has been an error while verifying contracts, no verified contracts nor bytecode mismatch errors are returned." + "There has been an error while verifying contracts, no verified contracts nor bytecode mismatch errors are returned.", ); return; } @@ -243,11 +300,18 @@ export class TenderlyService { response.results.bytecode_mismatch_errors !== undefined && response.results.bytecode_mismatch_errors !== null ) { - for (const bytecodeMismatchError of response.results.bytecode_mismatch_errors) { - logger.error("There has been a bytecode mismatch error while verifying contract.", bytecodeMismatchError); + for (const bytecodeMismatchError of response.results + .bytecode_mismatch_errors) { + logger.error( + "There has been a bytecode mismatch error while verifying contract.", + bytecodeMismatchError, + ); } } - if (response.results.verified_contracts !== undefined && response.results.verified_contracts !== null) { + if ( + response.results.verified_contracts !== undefined && + response.results.verified_contracts !== null + ) { for (const verifiedContract of response.results.verified_contracts) { const contractLink = `${TENDERLY_DASHBOARD_BASE_URL}/contract/${ CHAIN_ID_NETWORK_NAME_MAP[verifiedContract.network_id] @@ -260,18 +324,24 @@ export class TenderlyService { } catch (err) { const logCompliantApiError = convertToLogCompliantApiError(err); logger.error(logCompliantApiError); - logger.error(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`, + ); } } public async pushContractsMultiCompiler( request: TenderlyVerifyContractsRequest, tenderlyProject: string, - username: string + username: string, ): Promise { - logger.debug("Privately verifying contracts on tenderly. (Multi compiler version)"); + logger.debug( + "Privately verifying contracts on tenderly. (Multi compiler version)", + ); if (!TenderlyApiService.isAuthenticated()) { - logger.error(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`, + ); return; } @@ -282,26 +352,35 @@ export class TenderlyService { return; } - const res = await tenderlyApi.post(`/api/v1/accounts/${username}/projects/${tenderlyProject}/contracts/verify`, { - ...request, - }); + const res = await tenderlyApi.post( + `/api/v1/accounts/${username}/projects/${tenderlyProject}/contracts/verify`, + { + ...request, + }, + ); if (res.data === undefined || res.data === null) { logger.error( - "There was an error while privately verifying contracts on Tenderly. Obtained response is invalid." + "There was an error while privately verifying contracts on Tenderly. Obtained response is invalid.", ); return; } const response = convertToLogCompliantVerificationResponse(res.data); logger.trace("Verification response:", response); - if (response.compilation_errors !== undefined && response.compilation_errors !== null) { - logger.error("There have been compilation errors while verifying contracts.", response.compilation_errors); + if ( + response.compilation_errors !== undefined && + response.compilation_errors !== null + ) { + logger.error( + "There have been compilation errors while verifying contracts.", + response.compilation_errors, + ); return; } if (response.results === undefined || response.results === null) { logger.error( - "There has been an error while verifying contracts, no verified contracts nor bytecode mismatch errors are returned." + "There has been an error while verifying contracts, no verified contracts nor bytecode mismatch errors are returned.", ); return; } @@ -310,11 +389,18 @@ export class TenderlyService { response.results.bytecode_mismatch_errors !== undefined && response.results.bytecode_mismatch_errors !== null ) { - for (const bytecodeMismatchError of response.results.bytecode_mismatch_errors) { - logger.error("There has been a bytecode mismatch error while verifying contract.", bytecodeMismatchError); + for (const bytecodeMismatchError of response.results + .bytecode_mismatch_errors) { + logger.error( + "There has been a bytecode mismatch error while verifying contract.", + bytecodeMismatchError, + ); } } - if (response.results.verified_contracts !== undefined && response.results.verified_contracts !== null) { + if ( + response.results.verified_contracts !== undefined && + response.results.verified_contracts !== null + ) { for (const verifiedContract of response.results.verified_contracts) { await this.addContractToProject(username, tenderlyProject, { network_id: verifiedContract.network_id, @@ -336,7 +422,9 @@ export class TenderlyService { } catch (err) { const logCompliantApiError = convertToLogCompliantApiError(err); logger.error(logCompliantApiError); - logger.error(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`, + ); } } @@ -344,24 +432,32 @@ export class TenderlyService { request: TenderlyForkContractUploadRequest, tenderlyProject: string, username: string, - fork: string + fork: string, ): Promise { logger.info("Verifying contracts on fork."); if (!TenderlyApiService.isAuthenticated()) { - logger.error(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`, + ); return; } const tenderlyApi = TenderlyApiService.configureTenderlyRPCInstance(); try { - const res = await tenderlyApi.post(`/account/${username}/project/${tenderlyProject}/fork/${fork}/verify`, { - ...request, - }); + const res = await tenderlyApi.post( + `/account/${username}/project/${tenderlyProject}/fork/${fork}/verify`, + { + ...request, + }, + ); if (res.data === undefined || res.data === null) { - logger.error("There was an error while verifying contracts on fork. Obtained response is invalid."); + logger.error( + "There was an error while verifying contracts on fork. Obtained response is invalid.", + ); } - const logCompliantVerificationResponse = convertToLogCompliantForkVerificationResponse(res.data); + const logCompliantVerificationResponse = + convertToLogCompliantForkVerificationResponse(res.data); logger.trace("Verification response:", logCompliantVerificationResponse); const responseData: ContractResponse = res.data; @@ -376,7 +472,10 @@ export class TenderlyService { addresses += `${cont.contractName}, `; } - logger.error(`Error in ${this.pluginName}: ${NO_NEW_CONTRACTS_VERIFIED_ERR_MSG}`, addresses); + logger.error( + `Error in ${this.pluginName}: ${NO_NEW_CONTRACTS_VERIFIED_ERR_MSG}`, + addresses, + ); return; } @@ -388,7 +487,9 @@ export class TenderlyService { } catch (err) { const logCompliantApiError = convertToLogCompliantApiError(err); logger.error(logCompliantApiError); - logger.error(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`, + ); } } @@ -396,36 +497,45 @@ export class TenderlyService { request: TenderlyVerifyContractsRequest, tenderlyProject: string, username: string, - forkID: string + forkID: string, ): Promise { logger.info("Verifying contracts on fork. (Multi compiler version)"); if (!TenderlyApiService.isAuthenticated()) { - logger.error(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`, + ); return; } const tenderlyApi = TenderlyApiService.configureInstance(); try { const res = await tenderlyApi.post( - `api/v1/account/${username}/project/${tenderlyProject}/fork/${forkID}/contracts/verify`, { ...request } + `api/v1/account/${username}/project/${tenderlyProject}/fork/${forkID}/contracts/verify`, + { ...request }, ); if (res.data === undefined || res.data === null) { logger.error( - "There was an error while verifying contracts on fork (Multi compiler version). Obtained response is invalid." + "There was an error while verifying contracts on fork (Multi compiler version). Obtained response is invalid.", ); } const response = convertToLogCompliantVerificationResponse(res.data); logger.trace("Verification response:", response); - if (response.compilation_errors !== undefined && response.compilation_errors !== null) { - logger.error("There have been compilation errors while verifying contracts.", response.compilation_errors); + if ( + response.compilation_errors !== undefined && + response.compilation_errors !== null + ) { + logger.error( + "There have been compilation errors while verifying contracts.", + response.compilation_errors, + ); return; } if (response.results === undefined || response.results === null) { logger.error( - "There has been an error while verifying contracts, no verified contracts nor bytecode mismatch errors are returned." + "There has been an error while verifying contracts, no verified contracts nor bytecode mismatch errors are returned.", ); return; } @@ -434,15 +544,25 @@ export class TenderlyService { response.results.bytecode_mismatch_errors !== undefined && response.results.bytecode_mismatch_errors !== null ) { - for (const bytecodeMismatchError of response.results.bytecode_mismatch_errors) { - logger.error("There has been a bytecode mismatch error while verifying contract.", bytecodeMismatchError); + for (const bytecodeMismatchError of response.results + .bytecode_mismatch_errors) { + logger.error( + "There has been a bytecode mismatch error while verifying contract.", + bytecodeMismatchError, + ); } } - if (response.results.verified_contracts !== undefined && response.results.verified_contracts !== null) { + if ( + response.results.verified_contracts !== undefined && + response.results.verified_contracts !== null + ) { for (const verifiedContract of response.results.verified_contracts) { const contractLink = `${TENDERLY_DASHBOARD_BASE_URL}/${username}/${tenderlyProject}/fork/${forkID}`; let logMsg = `Contract ${verifiedContract.address} verified. You can view the contract at the fork: ${contractLink}`; - if (response.display_link != undefined && response.display_link != '') { + if ( + response.display_link != undefined && + response.display_link != "" + ) { logMsg = `Contract ${verifiedContract.address} verified. You can view the contract at: ${response.display_link}`; } console.log(logMsg); @@ -452,33 +572,44 @@ export class TenderlyService { } catch (err) { const logCompliantApiError = convertToLogCompliantApiError(err); logger.error(logCompliantApiError); - logger.error(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`, + ); } } public async addContractToProject( username: string, project: string, - request: TenderlyAddContractRequest + request: TenderlyAddContractRequest, ): Promise { logger.debug("Bulk adding contracts to project:", project); if (!TenderlyApiService.isAuthenticated()) { - logger.error(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`, + ); return; } const tenderlyApi = TenderlyApiService.configureInstance(); try { - const res = await tenderlyApi.post(`/api/v1/account/${username}/project/${project}/address`, { ...request }); + const res = await tenderlyApi.post( + `/api/v1/account/${username}/project/${project}/address`, + { ...request }, + ); if (res.status !== 200) { - logger.error(`There was an error while adding contracts to project. Status is ${res.status}`); + logger.error( + `There was an error while adding contracts to project. Status is ${res.status}`, + ); return; } logger.debug(`Added contract to project '${project}' successfully.`); } catch (err) { const logCompliantApiError = convertToLogCompliantApiError(err); logger.error(logCompliantApiError); - logger.error(`Error in ${this.pluginName}: ${API_ADD_CONTRACT_REQUEST_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${API_ADD_CONTRACT_REQUEST_ERR_MSG}`, + ); } } @@ -486,7 +617,9 @@ export class TenderlyService { logger.debug("Getting principal."); if (!TenderlyApiService.isAuthenticated()) { - logger.error(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`, + ); return null; } @@ -494,7 +627,9 @@ export class TenderlyService { try { const res = await tenderlyApi.get("/api/v1/user"); if (res.data === undefined || res.data === null) { - logger.error("There was an error while obtaining principal from Tenderly. Obtained response is invalid."); + logger.error( + "There was an error while obtaining principal from Tenderly. Obtained response is invalid.", + ); } logger.trace("Retrieved data:", { id: res.data.user.id }); @@ -505,7 +640,9 @@ export class TenderlyService { } catch (err) { const logCompliantApiError = convertToLogCompliantApiError(err); logger.error(logCompliantApiError); - logger.error(`Error in ${this.pluginName}: ${PRINCIPAL_FETCH_FAILED_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${PRINCIPAL_FETCH_FAILED_ERR_MSG}`, + ); } return null; } @@ -514,24 +651,34 @@ export class TenderlyService { logger.debug("Getting project slugs."); if (!TenderlyApiService.isAuthenticated()) { - logger.error(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`, + ); return []; } const tenderlyApi = TenderlyApiService.configureInstance(); try { - const res = await tenderlyApi.get(`/api/v1/account/${principalId}/projects`); + const res = await tenderlyApi.get( + `/api/v1/account/${principalId}/projects`, + ); if (res.data === undefined || res.data === null) { - logger.error("There was an error while obtaining project slug from Tenderly. Obtained response is invalid."); + logger.error( + "There was an error while obtaining project slug from Tenderly. Obtained response is invalid.", + ); } - const logCompliantProjects = convertToLogCompliantProjects(res.data.projects); + const logCompliantProjects = convertToLogCompliantProjects( + res.data.projects, + ); logger.trace("Obtained projects:", logCompliantProjects); return res.data.projects; } catch (err) { const logCompliantApiError = convertToLogCompliantApiError(err); logger.error(logCompliantApiError); - logger.error(`Error in ${this.pluginName}: ${PROJECTS_FETCH_FAILED_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${PROJECTS_FETCH_FAILED_ERR_MSG}`, + ); } return []; } @@ -546,30 +693,39 @@ export class TenderlyService { logger.info("Verifying contracts on devnet. (Multi compiler version)"); if (!accessKey && !TenderlyApiService.isAuthenticated()) { - logger.error(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`, + ); return; } const tenderlyApi = TenderlyApiService.configureInstance(accessKey); try { const res = await tenderlyApi.post( - `api/v1/account/${username}/project/${tenderlyProject}/devnet/endpoint/${devnetID}/contracts/verify`, { ...request } + `api/v1/account/${username}/project/${tenderlyProject}/devnet/endpoint/${devnetID}/contracts/verify`, + { ...request }, ); if (res.data === undefined || res.data === null) { logger.error( - "There was an error while verifying contracts on devnet (Multi compiler version). Obtained response is invalid." + "There was an error while verifying contracts on devnet (Multi compiler version). Obtained response is invalid.", ); } const response = convertToLogCompliantVerificationResponse(res.data); logger.trace("Verification response:", response); - if (response.compilation_errors !== undefined && response.compilation_errors !== null) { - logger.error("There have been compilation errors while verifying contracts.", response.compilation_errors); + if ( + response.compilation_errors !== undefined && + response.compilation_errors !== null + ) { + logger.error( + "There have been compilation errors while verifying contracts.", + response.compilation_errors, + ); return; } if (response.results === undefined || response.results === null) { logger.error( - "There has been an error while verifying contracts, no verified contracts nor bytecode mismatch errors are returned." + "There has been an error while verifying contracts, no verified contracts nor bytecode mismatch errors are returned.", ); return; } @@ -578,11 +734,18 @@ export class TenderlyService { response.results.bytecode_mismatch_errors !== undefined && response.results.bytecode_mismatch_errors !== null ) { - for (const bytecodeMismatchError of response.results.bytecode_mismatch_errors) { - logger.error("There has been a bytecode mismatch error while verifying contract.", bytecodeMismatchError); + for (const bytecodeMismatchError of response.results + .bytecode_mismatch_errors) { + logger.error( + "There has been a bytecode mismatch error while verifying contract.", + bytecodeMismatchError, + ); } } - if (response.results.verified_contracts !== undefined && response.results.verified_contracts !== null) { + if ( + response.results.verified_contracts !== undefined && + response.results.verified_contracts !== null + ) { for (const verifiedContract of response.results.verified_contracts) { const contractLink = response.display_link; const logMsg = `Contract ${verifiedContract.address} verified. You can view the contract at the devnet: ${contractLink}`; @@ -593,7 +756,9 @@ export class TenderlyService { } catch (err) { const logCompliantApiError = convertToLogCompliantApiError(err); logger.error(logCompliantApiError); - logger.error(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); + logger.error( + `Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`, + ); } } } diff --git a/packages/tenderly-core/src/internal/core/types/Requests.ts b/packages/tenderly-core/src/internal/core/types/Requests.ts index eec6cbd6..c44f743b 100644 --- a/packages/tenderly-core/src/internal/core/types/Requests.ts +++ b/packages/tenderly-core/src/internal/core/types/Requests.ts @@ -1,4 +1,8 @@ -import { TenderlyContract, TenderlyContractConfig, TenderlyVerificationContract } from "./Contract"; +import { + TenderlyContract, + TenderlyContractConfig, + TenderlyVerificationContract, +} from "./Contract"; export interface TenderlyContractUploadRequest { config: TenderlyContractConfig; diff --git a/packages/tenderly-core/src/internal/core/types/Responses.ts b/packages/tenderly-core/src/internal/core/types/Responses.ts index 8158f7ac..f755c56d 100644 --- a/packages/tenderly-core/src/internal/core/types/Responses.ts +++ b/packages/tenderly-core/src/internal/core/types/Responses.ts @@ -1,4 +1,8 @@ -import { ApiContract, BytecodeMismatchError, CompilationError } from "./Contract"; +import { + ApiContract, + BytecodeMismatchError, + CompilationError, +} from "./Contract"; export interface ContractResponse { contracts: ApiContract[]; @@ -13,5 +17,5 @@ export interface VerificationResult { export interface VerifyContractsResponse { compilation_errors: CompilationError[]; results: VerificationResult[]; - display_link?: string + display_link?: string; } diff --git a/packages/tenderly-core/src/types/TenderlyConfig.ts b/packages/tenderly-core/src/types/TenderlyConfig.ts index 3311d48c..ab3a66f2 100644 --- a/packages/tenderly-core/src/types/TenderlyConfig.ts +++ b/packages/tenderly-core/src/types/TenderlyConfig.ts @@ -7,4 +7,4 @@ export interface TenderlyConfig { username: string; head?: string; fork?: string; -} \ No newline at end of file +} diff --git a/packages/tenderly-core/src/utils/config.ts b/packages/tenderly-core/src/utils/config.ts index b53eefc9..3515e98a 100644 --- a/packages/tenderly-core/src/utils/config.ts +++ b/packages/tenderly-core/src/utils/config.ts @@ -16,13 +16,16 @@ export function getConfig(): TenderlyConfig { const tenderlyConfig = yaml.load(fileData.toString()) as TenderlyConfig; - const logCompliantTenderlyConfig = convertToLogCompliantTenderlyConfig(tenderlyConfig); + const logCompliantTenderlyConfig = + convertToLogCompliantTenderlyConfig(tenderlyConfig); logger.trace("Checking config:", logCompliantTenderlyConfig); return tenderlyConfig; } - logger.warn("Tenderly config doesn't exist, empty string values are returned instead."); + logger.warn( + "Tenderly config doesn't exist, empty string values are returned instead.", + ); return { access_key: "", access_key_id: "", @@ -34,9 +37,12 @@ export function getConfig(): TenderlyConfig { } export function writeConfig(config: TenderlyConfig): void { - logger.trace(`Writing tenderly config to a file @ ${configDir}/${configFilePath}`); + logger.trace( + `Writing tenderly config to a file @ ${configDir}/${configFilePath}`, + ); - const logCompliantTenderlyConfig = convertToLogCompliantTenderlyConfig(config); + const logCompliantTenderlyConfig = + convertToLogCompliantTenderlyConfig(config); logger.trace("Checking config:", logCompliantTenderlyConfig); fs.mkdirSync(configDir, { recursive: true }); @@ -46,7 +52,9 @@ export function writeConfig(config: TenderlyConfig): void { export function configExists(): boolean { logger.trace("Checking if tenderly config exists."); const exists = fs.existsSync(configFilePath); - logger.trace(exists ? "Tenderly config exists." : "Tenderly config doesn't exist."); + logger.trace( + exists ? "Tenderly config exists." : "Tenderly config doesn't exist.", + ); return exists; } @@ -55,7 +63,10 @@ export function isAccessTokenSet(): boolean { logger.trace("Determining if access token in tenderly config file is set."); const config = getConfig(); - const isSet = config.access_key !== undefined && config.access_key !== null && config.access_key !== ""; + const isSet = + config.access_key !== undefined && + config.access_key !== null && + config.access_key !== ""; logger.trace(isSet ? "Access key is set." : "Access key is not set."); return isSet; diff --git a/packages/tenderly-core/src/utils/log-compliance.ts b/packages/tenderly-core/src/utils/log-compliance.ts index c09912fc..8dc49b31 100644 --- a/packages/tenderly-core/src/utils/log-compliance.ts +++ b/packages/tenderly-core/src/utils/log-compliance.ts @@ -28,9 +28,12 @@ export function convertToLogCompliantApiError(err: any) { } } -export function convertToLogCompliantForkVerificationResponse(res: ContractResponse) { +export function convertToLogCompliantForkVerificationResponse( + res: ContractResponse, +) { const logCompliantContracts = convertToLogCompliantContracts(res.contracts); - const logCompliantBytecodeMismatchErrors = convertToLogCompliantBytecodeMismatchErrors(res.bytecode_mismatch_errors); + const logCompliantBytecodeMismatchErrors = + convertToLogCompliantBytecodeMismatchErrors(res.bytecode_mismatch_errors); return { contracts: logCompliantContracts, @@ -76,7 +79,9 @@ export function convertToLogCompliantContracts(contracts: ApiContract[]) { return logCompliantContracts; } -export function convertToLogCompliantBytecodeMismatchErrors(bytecodeMismatchErrors: BytecodeMismatchError[]) { +export function convertToLogCompliantBytecodeMismatchErrors( + bytecodeMismatchErrors: BytecodeMismatchError[], +) { if (bytecodeMismatchErrors === undefined || bytecodeMismatchErrors === null) { return undefined; } @@ -94,9 +99,14 @@ export function convertToLogCompliantBytecodeMismatchErrors(bytecodeMismatchErro return logCompliantBytecodeMismatchErrors; } -export function convertToLogCompliantVerificationResponse(res: VerifyContractsResponse) { - const logCompliantCompilationErrors = convertToLogCompliantCompilationErrors(res?.compilation_errors); - const logCompliantVerificationResults = convertToLogCompliantVerificationResults(res?.results); +export function convertToLogCompliantVerificationResponse( + res: VerifyContractsResponse, +) { + const logCompliantCompilationErrors = convertToLogCompliantCompilationErrors( + res?.compilation_errors, + ); + const logCompliantVerificationResults = + convertToLogCompliantVerificationResults(res?.results); return { results: logCompliantVerificationResults, @@ -105,7 +115,9 @@ export function convertToLogCompliantVerificationResponse(res: VerifyContractsRe }; } -function convertToLogCompliantVerificationResults(results: VerificationResult[]) { +function convertToLogCompliantVerificationResults( + results: VerificationResult[], +) { if (results === undefined || results === null) { return undefined; } @@ -114,7 +126,10 @@ function convertToLogCompliantVerificationResults(results: VerificationResult[]) const logCompliantBytecodeMismatchErrors = []; for (const res of results) { - if (res.bytecode_mismatch_error !== undefined && res.bytecode_mismatch_error !== null) { + if ( + res.bytecode_mismatch_error !== undefined && + res.bytecode_mismatch_error !== null + ) { logCompliantBytecodeMismatchErrors.push({ contract_id: res.bytecode_mismatch_error.contract_id, expected: res.bytecode_mismatch_error.expected, @@ -159,7 +174,9 @@ function convertToLogCompliantVerificationResults(results: VerificationResult[]) }; } -function convertToLogCompliantCompilationErrors(compilationErrors: CompilationError[]) { +function convertToLogCompliantCompilationErrors( + compilationErrors: CompilationError[], +) { if (compilationErrors === undefined || compilationErrors === null) { return undefined; } @@ -249,15 +266,21 @@ export function convertToLogCompliantTenderlyConfig(config: TenderlyConfig) { : "undefined or null or empty string", account_id: config.account_id, username: - config.username !== undefined && config.username !== null && config.username !== "" + config.username !== undefined && + config.username !== null && + config.username !== "" ? "set in 'username' field" : "undefined or null or empty string", access_key: - config.access_key !== undefined && config.access_key !== null && config.access_key !== "" + config.access_key !== undefined && + config.access_key !== null && + config.access_key !== "" ? "super secret access_key is set in 'access_key' field" : "undefined or null or empty string", access_key_id: - config.access_key_id !== undefined && config.access_key_id !== null && config.access_key_id !== "" + config.access_key_id !== undefined && + config.access_key_id !== null && + config.access_key_id !== "" ? "super secret access_key_id is set in 'access_key' field" : "undefined or null or empty string", }; diff --git a/packages/tenderly-hardhat/src/Tenderly.ts b/packages/tenderly-hardhat/src/Tenderly.ts index f1297484..e10ed6b4 100644 --- a/packages/tenderly-hardhat/src/Tenderly.ts +++ b/packages/tenderly-hardhat/src/Tenderly.ts @@ -13,7 +13,10 @@ import { NETWORK_NAME_CHAIN_ID_MAP } from "tenderly/common/constants"; import { logger } from "./utils/logger"; import { ContractByName, Metadata } from "./tenderly/types"; -import { CONTRACTS_NOT_DETECTED, NO_COMPILER_FOUND_FOR_CONTRACT_ERR_MSG } from "./tenderly/errors"; +import { + CONTRACTS_NOT_DETECTED, + NO_COMPILER_FOUND_FOR_CONTRACT_ERR_MSG, +} from "./tenderly/errors"; import { extractCompilerVersion, getCompilerDataFromContracts, @@ -43,9 +46,15 @@ export class Tenderly { public async verify(...contracts: any[]): Promise { logger.info("Verification invoked."); - const flatContracts: ContractByName[] = contracts.reduce((accumulator, value) => accumulator.concat(value), []); + const flatContracts: ContractByName[] = contracts.reduce( + (accumulator, value) => accumulator.concat(value), + [], + ); const verificationType = this._getVerificationType(); - const platformID = verificationType === VERIFICATION_TYPES.FORK ? this.tenderlyNetwork.forkID : this.tenderlyNetwork.devnetID + const platformID = + verificationType === VERIFICATION_TYPES.FORK + ? this.tenderlyNetwork.forkID + : this.tenderlyNetwork.devnetID; const requestData = await makeVerifyContractsRequest( this.env, @@ -53,24 +62,30 @@ export class Tenderly { platformID, ); if (requestData === null) { - logger.error("Verification failed due to bad processing of the data in /artifacts directory."); + logger.error( + "Verification failed due to bad processing of the data in /artifacts directory.", + ); return; } if (this._isVerificationOnPlatform(verificationType)) { - logger.info(`Network parameter is set to '${this.getNetworkName()}', redirecting to ${verificationType} verification.`); + logger.info( + `Network parameter is set to '${this.getNetworkName()}', redirecting to ${verificationType} verification.`, + ); await this._throwIfUsernameOrProjectNotSet(); return this.tenderlyNetwork.verify(requestData); } if (verificationType === VERIFICATION_TYPES.PRIVATE) { - logger.info("Private verification flag is set to true, redirecting to private verification."); + logger.info( + "Private verification flag is set to true, redirecting to private verification.", + ); await this._throwIfUsernameOrProjectNotSet(); return this.tenderlyService.pushContractsMultiCompiler( requestData, this.env.config.tenderly.project, - this.env.config.tenderly.username + this.env.config.tenderly.username, ); } @@ -78,40 +93,44 @@ export class Tenderly { return this.tenderlyService.verifyContractsMultiCompiler(requestData); } - public async verifyMultiCompilerAPI(request: TenderlyVerifyContractsRequest): Promise { + public async verifyMultiCompilerAPI( + request: TenderlyVerifyContractsRequest, + ): Promise { logger.info("Invoked verification (multi compiler version) through API."); logger.trace("Request data:", request); switch (this._getVerificationType()) { case VERIFICATION_TYPES.FORK: logger.error( - `Error in ${PLUGIN_NAME}: Network parameter is set to 'tenderly' and verifyMultiCompilerAPI() is not available for fork deployments, please use verifyForkAPI().` + `Error in ${PLUGIN_NAME}: Network parameter is set to 'tenderly' and verifyMultiCompilerAPI() is not available for fork deployments, please use verifyForkAPI().`, ); break; case VERIFICATION_TYPES.DEVNET: logger.error( - `Error in ${PLUGIN_NAME}: Network parameter is set to '${this.getNetworkName()}' and verifyMultiCompilerAPI() is not available for devnet deployments` + `Error in ${PLUGIN_NAME}: Network parameter is set to '${this.getNetworkName()}' and verifyMultiCompilerAPI() is not available for devnet deployments`, ); break; case VERIFICATION_TYPES.PRIVATE: if (this.env.config.tenderly?.project === undefined) { logger.error( - `Error in ${PLUGIN_NAME}: Please provide the project field in the tenderly object in hardhat.config.js` + `Error in ${PLUGIN_NAME}: Please provide the project field in the tenderly object in hardhat.config.js`, ); return; } if (this.env.config.tenderly?.username === undefined) { logger.error( - `Error in ${PLUGIN_NAME}: Please provide the username field in the tenderly object in hardhat.config.js` + `Error in ${PLUGIN_NAME}: Please provide the username field in the tenderly object in hardhat.config.js`, ); return; } - logger.info("Private verification flag is set to true, redirecting to private verification."); + logger.info( + "Private verification flag is set to true, redirecting to private verification.", + ); await this.tenderlyService.pushContractsMultiCompiler( request, this.env.config.tenderly.project, - this.env.config.tenderly.username + this.env.config.tenderly.username, ); break; case VERIFICATION_TYPES.PUBLIC: @@ -125,36 +144,50 @@ export class Tenderly { request: TenderlyVerifyContractsRequest, tenderlyProject: string, username: string, - forkID: string + forkID: string, ): Promise { - logger.info("Invoked fork verification through API request. (Multi compiler version)"); + logger.info( + "Invoked fork verification through API request. (Multi compiler version)", + ); if (!isTenderlyNetworkConfig(this.env.network.config)) { logger.error( - `Error in ${PLUGIN_NAME}: Network parameter is not set to 'tenderly' and verifyForkAPI() is only available for tenderly fork deployments, please use --network tenderly.` + `Error in ${PLUGIN_NAME}: Network parameter is not set to 'tenderly' and verifyForkAPI() is only available for tenderly fork deployments, please use --network tenderly.`, ); return; } await this._throwIfUsernameOrProjectNotSet(); - await this.tenderlyNetwork.verifyMultiCompilerAPI(request, tenderlyProject, username, forkID); + await this.tenderlyNetwork.verifyMultiCompilerAPI( + request, + tenderlyProject, + username, + forkID, + ); } public async verifyDevnetMultiCompilerAPI( request: TenderlyVerifyContractsRequest, tenderlyProject: string, username: string, - devnetID: string + devnetID: string, ): Promise { - logger.info("Invoked devnet verification through API request. (Multi compiler version)"); + logger.info( + "Invoked devnet verification through API request. (Multi compiler version)", + ); if (!isTenderlyNetworkConfig(this.env.network.config)) { logger.error( - `Error in ${PLUGIN_NAME}: Network parameter is not set to 'devnet' and verifyDevnetMultiCompilerAPI() is only available for tenderly devnet deployments, please use --network devnet.` + `Error in ${PLUGIN_NAME}: Network parameter is not set to 'devnet' and verifyDevnetMultiCompilerAPI() is only available for tenderly devnet deployments, please use --network devnet.`, ); return; } await this._throwIfUsernameOrProjectNotSet(); - await this.tenderlyNetwork.verifyDevnetMultiCompilerAPI(request, tenderlyProject, username, devnetID); + await this.tenderlyNetwork.verifyDevnetMultiCompilerAPI( + request, + tenderlyProject, + username, + devnetID, + ); } public network(): TenderlyNetwork { @@ -162,7 +195,7 @@ export class Tenderly { } public getNetworkName(): string { - return this.env.network.name + return this.env.network.name; } public setNetwork(network: TenderlyNetwork): TenderlyNetwork { @@ -174,11 +207,17 @@ export class Tenderly { private _getVerificationType(): string { if (isTenderlyNetworkConfig(this.env.network.config)) { - return this.tenderlyNetwork.devnetID !== undefined ? VERIFICATION_TYPES.DEVNET : VERIFICATION_TYPES.FORK + return this.tenderlyNetwork.devnetID !== undefined + ? VERIFICATION_TYPES.DEVNET + : VERIFICATION_TYPES.FORK; } const priv = this.env.config.tenderly?.privateVerification; - if (priv !== undefined && priv && !isTenderlyNetworkConfig(this.env.network.config)) { + if ( + priv !== undefined && + priv && + !isTenderlyNetworkConfig(this.env.network.config) + ) { return VERIFICATION_TYPES.PRIVATE; } @@ -192,28 +231,30 @@ export class Tenderly { private async _throwIfUsernameOrProjectNotSet(): Promise { if (this.env.config.tenderly?.project === undefined) { throw Error( - `Error in ${PLUGIN_NAME}: Please provide the project field in the tenderly object in hardhat.config.js` + `Error in ${PLUGIN_NAME}: Please provide the project field in the tenderly object in hardhat.config.js`, ); } if (this.env.config.tenderly?.username === undefined) { throw Error( - `Error in ${PLUGIN_NAME}: Please provide the username field in the tenderly object in hardhat.config.js` + `Error in ${PLUGIN_NAME}: Please provide the username field in the tenderly object in hardhat.config.js`, ); } } - public async verifyAPI(request: TenderlyContractUploadRequest): Promise { + public async verifyAPI( + request: TenderlyContractUploadRequest, + ): Promise { logger.info("Invoked public verification through API request."); if (isTenderlyNetworkConfig(this.env.network.config)) { - if (this._getVerificationType() === VERIFICATION_TYPES.DEVNET){ + if (this._getVerificationType() === VERIFICATION_TYPES.DEVNET) { logger.error( - `Error in ${PLUGIN_NAME}: Network parameter is set to '${this.getNetworkName()}' and verifyAPI() is not available for devnet deployments.` + `Error in ${PLUGIN_NAME}: Network parameter is set to '${this.getNetworkName()}' and verifyAPI() is not available for devnet deployments.`, ); - return + return; } logger.error( - `Error in ${PLUGIN_NAME}: Network parameter is set to 'tenderly' and verifyAPI() is not available for fork deployments, please use verifyForkAPI().` + `Error in ${PLUGIN_NAME}: Network parameter is set to 'tenderly' and verifyAPI() is not available for fork deployments, please use verifyForkAPI().`, ); return; } @@ -225,40 +266,49 @@ export class Tenderly { request: TenderlyForkContractUploadRequest, tenderlyProject: string, username: string, - forkID: string + forkID: string, ): Promise { logger.info("Invoked fork verification through API request."); if (this.env.network.name !== "tenderly") { logger.error( - `Error in ${PLUGIN_NAME}: Network parameter is not set to 'tenderly' and verifyForkAPI() is only available for tenderly fork deployments, please use --network tenderly.` + `Error in ${PLUGIN_NAME}: Network parameter is not set to 'tenderly' and verifyForkAPI() is only available for tenderly fork deployments, please use --network tenderly.`, ); return; } - await this.tenderlyNetwork.verifyAPI(request, tenderlyProject, username, forkID); + await this.tenderlyNetwork.verifyAPI( + request, + tenderlyProject, + username, + forkID, + ); } public async pushAPI( request: TenderlyContractUploadRequest, tenderlyProject: string, - username: string + username: string, ): Promise { logger.info("Invoked pushing contracts through API."); if (isTenderlyNetworkConfig(this.env.network.config)) { - if (this._getVerificationType() === VERIFICATION_TYPES.DEVNET){ + if (this._getVerificationType() === VERIFICATION_TYPES.DEVNET) { logger.error( - `Error in ${PLUGIN_NAME}: Network parameter is set to '${this.getNetworkName()}' and pushAPI() is not available for devnet deployments.` + `Error in ${PLUGIN_NAME}: Network parameter is set to '${this.getNetworkName()}' and pushAPI() is not available for devnet deployments.`, ); - return + return; } logger.error( - `Error in ${PLUGIN_NAME}: Network parameter is set to 'tenderly' and pushAPI() is not available for fork deployments, please use verifyForkAPI().` + `Error in ${PLUGIN_NAME}: Network parameter is set to 'tenderly' and pushAPI() is not available for fork deployments, please use verifyForkAPI().`, ); return; } - await this.tenderlyService.pushContracts(request, tenderlyProject, username); + await this.tenderlyService.pushContracts( + request, + tenderlyProject, + username, + ); } public async persistArtifacts(...contracts: ContractByName[]) { @@ -269,7 +319,10 @@ export class Tenderly { } const sourcePaths = await this.env.run("compile:solidity:get-source-paths"); - const sourceNames = await this.env.run("compile:solidity:get-source-names", { sourcePaths }); + const sourceNames = await this.env.run( + "compile:solidity:get-source-names", + { sourcePaths }, + ); const data = await this.env.run("compile:solidity:get-dependency-graph", { sourceNames, }); @@ -296,11 +349,12 @@ export class Tenderly { : contract.network; if (network === undefined) { console.log( - `Error in ${PLUGIN_NAME}: Please provide a network via the hardhat --network argument or directly in the contract` + `Error in ${PLUGIN_NAME}: Please provide a network via the hardhat --network argument or directly in the contract`, ); continue; } - let chainID: string = NETWORK_NAME_CHAIN_ID_MAP[network!.toLowerCase()]; + let chainID: string = + NETWORK_NAME_CHAIN_ID_MAP[network!.toLowerCase()]; if (this.env.config.networks[network!].chainId !== undefined) { chainID = this.env.config.networks[network!].chainId!.toString(); } @@ -308,10 +362,13 @@ export class Tenderly { if (chainID === undefined) { chainID = DEFAULT_CHAIN_ID; } - const deploymentsFolder = this.env.config?.tenderly?.deploymentsDir ?? "deployments"; + const deploymentsFolder = + this.env.config?.tenderly?.deploymentsDir ?? "deployments"; const destPath = `${deploymentsFolder}${sep}${network!.toLowerCase()}_${chainID}${sep}`; const contractDataPath = `${this.env.config.paths.artifacts}${sep}${sourcePath}${sep}${name}.json`; - const contractData = JSON.parse(fs.readFileSync(contractDataPath).toString()); + const contractData = JSON.parse( + fs.readFileSync(contractDataPath).toString(), + ); const metadata: Metadata = { defaultCompiler: { @@ -339,13 +396,18 @@ export class Tenderly { logger.trace("Processed artifact: ", artifact); - fs.outputFileSync(`${destPath}${name}.json`, JSON.stringify(artifact)); + fs.outputFileSync( + `${destPath}${name}.json`, + JSON.stringify(artifact), + ); } } }); } - private async _filterContracts(flatContracts: ContractByName[]): Promise { + private async _filterContracts( + flatContracts: ContractByName[], + ): Promise { logger.info("Processing data needed for verification."); let contract: ContractByName; @@ -354,7 +416,10 @@ export class Tenderly { requestData = await this._getContractData(flatContracts); logger.silly("Processed request data:", requestData); } catch (e) { - logger.error("Error caught while trying to process contracts by name: ", e); + logger.error( + "Error caught while trying to process contracts by name: ", + e, + ); return null; } @@ -365,17 +430,19 @@ export class Tenderly { : contract.network; if (network === undefined) { logger.error( - `Error in ${PLUGIN_NAME}: Please provide a network via the hardhat --network argument or directly in the contract` + `Error in ${PLUGIN_NAME}: Please provide a network via the hardhat --network argument or directly in the contract`, ); return null; } logger.trace("Found network is:", network); const index = requestData.contracts.findIndex( - (requestContract) => requestContract.contractName === contract.name + (requestContract) => requestContract.contractName === contract.name, ); if (index === -1) { - logger.error(`Contract '${contract.name}' was not found among the contracts in /artifacts.`); + logger.error( + `Contract '${contract.name}' was not found among the contracts in /artifacts.`, + ); continue; } let chainID: string = NETWORK_NAME_CHAIN_ID_MAP[network!.toLowerCase()]; @@ -386,7 +453,7 @@ export class Tenderly { if (chainID === undefined) { logger.error( - `Error in ${PLUGIN_NAME}: Couldn't identify network. Please provide a chainId in the network config object` + `Error in ${PLUGIN_NAME}: Couldn't identify network. Please provide a chainId in the network config object`, ); return null; } @@ -403,10 +470,16 @@ export class Tenderly { return requestData; } - private async _getContractData(flatContracts: ContractByName[]): Promise { + private async _getContractData( + flatContracts: ContractByName[], + ): Promise { const contracts = await getContracts(this.env, flatContracts); - const config = getCompilerDataFromContracts(contracts, flatContracts, this.env.config); + const config = getCompilerDataFromContracts( + contracts, + flatContracts, + this.env.config, + ); if (config === undefined) { logger.error(NO_COMPILER_FOUND_FOR_CONTRACT_ERR_MSG); } @@ -417,6 +490,9 @@ export class Tenderly { }; } private _isVerificationOnPlatform(verificationType: string): boolean { - return verificationType === VERIFICATION_TYPES.DEVNET || verificationType === VERIFICATION_TYPES.FORK + return ( + verificationType === VERIFICATION_TYPES.DEVNET || + verificationType === VERIFICATION_TYPES.FORK + ); } } diff --git a/packages/tenderly-hardhat/src/TenderlyNetwork.ts b/packages/tenderly-hardhat/src/TenderlyNetwork.ts index 667d6199..eb086634 100644 --- a/packages/tenderly-hardhat/src/TenderlyNetwork.ts +++ b/packages/tenderly-hardhat/src/TenderlyNetwork.ts @@ -2,7 +2,10 @@ import * as axios from "axios"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { TenderlyService } from "tenderly"; -import { TenderlyForkContractUploadRequest, TenderlyVerifyContractsRequest } from "tenderly/types"; +import { + TenderlyForkContractUploadRequest, + TenderlyVerifyContractsRequest, +} from "tenderly/types"; import { getConfig, writeConfig } from "tenderly/utils/config"; import { TENDERLY_JSON_RPC_BASE_URL } from "tenderly/common/constants"; @@ -10,7 +13,11 @@ import { convertToLogCompliantForkInitializeResponse } from "tenderly/utils/log- import { PLUGIN_NAME } from "./constants"; import { ContractByName } from "./tenderly/types"; import { NO_COMPILER_FOUND_FOR_CONTRACT_ERR_MSG } from "./tenderly/errors"; -import { getCompilerDataFromContracts, getContracts, isTenderlyNetworkConfig } from "./utils/util"; +import { + getCompilerDataFromContracts, + getContracts, + isTenderlyNetworkConfig, +} from "./utils/util"; import { logger } from "./utils/logger"; export class TenderlyNetwork { @@ -24,7 +31,6 @@ export class TenderlyNetwork { public env: HardhatRuntimeEnvironment; public devnetID: string | undefined; - private tenderlyService = new TenderlyService(PLUGIN_NAME); constructor(hre: HardhatRuntimeEnvironment) { @@ -45,7 +51,7 @@ export class TenderlyNetwork { "url" in hre.network.config && hre.network.config.url !== undefined ) { - if(hre.network.config.url.includes("devnet")) { + if (hre.network.config.url.includes("devnet")) { this.devnetID = hre.network.config.url.split("/").pop(); logger.info("Devnet ID is:", this.devnetID); } else { @@ -115,7 +121,7 @@ export class TenderlyNetwork { this.devnetID, this.env.config.tenderly.accessKey, ); - return + return; } if (this.head === undefined && this.forkID === undefined) { @@ -127,7 +133,7 @@ export class TenderlyNetwork { requestData, this.env.config.tenderly.project, this.env.config.tenderly.username, - this.forkID! + this.forkID!, ); } @@ -135,14 +141,14 @@ export class TenderlyNetwork { request: TenderlyVerifyContractsRequest, tenderlyProject: string, username: string, - forkID: string + forkID: string, ) { logger.info("Invoked fork verification via API."); await this.tenderlyService.verifyForkContractsMultiCompiler( - request, - tenderlyProject, - username, - forkID + request, + tenderlyProject, + username, + forkID, ); } @@ -150,7 +156,7 @@ export class TenderlyNetwork { request: TenderlyVerifyContractsRequest, tenderlyProject: string, username: string, - devnetID: string + devnetID: string, ) { logger.info("Invoked devnet verification via API."); await this.tenderlyService.verifyDevnetContractsMultiCompiler( @@ -165,10 +171,15 @@ export class TenderlyNetwork { request: TenderlyForkContractUploadRequest, tenderlyProject: string, username: string, - forkID: string + forkID: string, ) { logger.info("Invoked fork verification via API."); - await this.tenderlyService.verifyForkContracts(request, tenderlyProject, username, forkID); + await this.tenderlyService.verifyForkContracts( + request, + tenderlyProject, + username, + forkID, + ); } public getHead(): string | undefined { @@ -207,19 +218,27 @@ export class TenderlyNetwork { return; } if (this.env.config.tenderly?.forkNetwork === undefined) { - logger.error("There is no information about the fork network. Fork won't be initialized"); + logger.error( + "There is no information about the fork network. Fork won't be initialized", + ); return; } const username: string = this.env.config.tenderly.username; const projectID: string = this.env.config.tenderly.project; - logger.trace("ProjectID obtained from tenderly configuration:", { projectID }); + logger.trace("ProjectID obtained from tenderly configuration:", { + projectID, + }); try { - const resp = await this.tenderlyJsonRpc.post(`/account/${username}/project/${projectID}/fork`, { - network_id: this.env.config.tenderly.forkNetwork, - }); - const logCompliantInitializeForkResponse = convertToLogCompliantForkInitializeResponse(resp); + const resp = await this.tenderlyJsonRpc.post( + `/account/${username}/project/${projectID}/fork`, + { + network_id: this.env.config.tenderly.forkNetwork, + }, + ); + const logCompliantInitializeForkResponse = + convertToLogCompliantForkInitializeResponse(resp); logger.trace("Initialized fork:", logCompliantInitializeForkResponse); this.head = resp.data.root_transaction.id; @@ -245,25 +264,35 @@ export class TenderlyNetwork { writeConfig(tdlyGlobalConfig); } - private async _filterContracts(flatContracts: ContractByName[]): Promise { + private async _filterContracts( + flatContracts: ContractByName[], + ): Promise { logger.info("Processing data needed for fork verification."); let contract: ContractByName; let requestData: TenderlyForkContractUploadRequest; try { requestData = await this._getForkContractData(flatContracts); - logger.silly("Obtained request data needed for fork verification:", requestData); + logger.silly( + "Obtained request data needed for fork verification:", + requestData, + ); } catch (e) { - logger.error("Caught and error while trying to obtain data needed for fork verification", e); + logger.error( + "Caught and error while trying to obtain data needed for fork verification", + e, + ); return null; } for (contract of flatContracts) { const index = requestData.contracts.findIndex( - (requestContract) => requestContract.contractName === contract.name + (requestContract) => requestContract.contractName === contract.name, ); if (index === -1) { - logger.error(`Couldn't find a contract '${contract.name}' among the obtained request data.`); + logger.error( + `Couldn't find a contract '${contract.name}' among the obtained request data.`, + ); continue; } @@ -280,15 +309,23 @@ export class TenderlyNetwork { return requestData; } - private async _getForkContractData(flatContracts: ContractByName[]): Promise { + private async _getForkContractData( + flatContracts: ContractByName[], + ): Promise { logger.trace("Getting contract data needed for fork verification."); const contracts = await getContracts(this.env, flatContracts); if (contracts.length === 0) { - throw new Error("Fork verification failed due to bad processing of data in /artifacts folder."); + throw new Error( + "Fork verification failed due to bad processing of data in /artifacts folder.", + ); } - const solcConfig = getCompilerDataFromContracts(contracts, flatContracts, this.env.config); + const solcConfig = getCompilerDataFromContracts( + contracts, + flatContracts, + this.env.config, + ); if (solcConfig === undefined) { logger.error(NO_COMPILER_FOUND_FOR_CONTRACT_ERR_MSG); } @@ -303,7 +340,7 @@ export class TenderlyNetwork { private _checkNetwork(): boolean { if (!isTenderlyNetworkConfig(this.env.network.config)) { logger.error( - `Warning in ${PLUGIN_NAME}: Network is not set to 'tenderly'. Please call the task again with --network tenderly` + `Warning in ${PLUGIN_NAME}: Network is not set to 'tenderly'. Please call the task again with --network tenderly`, ); return false; } diff --git a/packages/tenderly-hardhat/src/constants.ts b/packages/tenderly-hardhat/src/constants.ts index ae8b6284..8a933160 100644 --- a/packages/tenderly-hardhat/src/constants.ts +++ b/packages/tenderly-hardhat/src/constants.ts @@ -6,4 +6,5 @@ export const VERIFICATION_TYPES = { PUBLIC: "public", DEVNET: "devnet", }; -export const CONTRACT_NAME_PLACEHOLDER = "HARDHAT_TENDERLY_CONTRACT_NAME_PLACEHOLDER"; +export const CONTRACT_NAME_PLACEHOLDER = + "HARDHAT_TENDERLY_CONTRACT_NAME_PLACEHOLDER"; diff --git a/packages/tenderly-hardhat/src/index.ts b/packages/tenderly-hardhat/src/index.ts index b690163a..68729767 100644 --- a/packages/tenderly-hardhat/src/index.ts +++ b/packages/tenderly-hardhat/src/index.ts @@ -3,7 +3,10 @@ import "./tasks"; import * as tenderlyExtender from "./tenderly/extender"; -export function setup(cfg: { automaticVerifications: boolean } = { automaticVerifications: true }): void { - process.env.AUTOMATIC_VERIFICATION_ENABLED = cfg.automaticVerifications === true ? "true" : "false"; +export function setup( + cfg: { automaticVerifications: boolean } = { automaticVerifications: true }, +): void { + process.env.AUTOMATIC_VERIFICATION_ENABLED = + cfg.automaticVerifications === true ? "true" : "false"; tenderlyExtender.setup(); } diff --git a/packages/tenderly-hardhat/src/tasks/common/index.ts b/packages/tenderly-hardhat/src/tasks/common/index.ts index 61a92df0..0c2a8829 100644 --- a/packages/tenderly-hardhat/src/tasks/common/index.ts +++ b/packages/tenderly-hardhat/src/tasks/common/index.ts @@ -13,7 +13,7 @@ export async function extractContractData( contracts: string[], network: string | undefined, config: HardhatConfig, - run: RunTaskFunction + run: RunTaskFunction, ): Promise { logger.info("Extracting contract data."); @@ -87,7 +87,7 @@ export async function extractContractData( } if (chainID === undefined) { logger.error( - `Error in ${PLUGIN_NAME}: Couldn't identify network. Please provide a chainID in the network config object` + `Error in ${PLUGIN_NAME}: Couldn't identify network. Please provide a chainID in the network config object`, ); return []; } diff --git a/packages/tenderly-hardhat/src/tasks/push.ts b/packages/tenderly-hardhat/src/tasks/push.ts index 6dc08e0e..125cc71b 100644 --- a/packages/tenderly-hardhat/src/tasks/push.ts +++ b/packages/tenderly-hardhat/src/tasks/push.ts @@ -2,14 +2,20 @@ import { task } from "hardhat/config"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -task("tenderly:push", "Verifies contracts on Tenderly based on the configuration in hardhat.config.js.") +task( + "tenderly:push", + "Verifies contracts on Tenderly based on the configuration in hardhat.config.js.", +) .addOptionalVariadicPositionalParam( "contracts", - "Addresses and names of contracts that will be verified formatted ContractName=Address" + "Addresses and names of contracts that will be verified formatted ContractName=Address", ) .setAction(pushContracts); -async function pushContracts({ contracts }: any, hre: HardhatRuntimeEnvironment) { +async function pushContracts( + { contracts }: any, + hre: HardhatRuntimeEnvironment, +) { new ColorLog("THIS TASK IS DEPRECATED. PLEASE USE 'tenderly:verify' TASK.") // .prependColor(ColorLog.BG.RED) .prependColor(ColorLog.TEXT.RED) diff --git a/packages/tenderly-hardhat/src/tasks/verify.ts b/packages/tenderly-hardhat/src/tasks/verify.ts index f3a5755e..0cbcc0bb 100644 --- a/packages/tenderly-hardhat/src/tasks/verify.ts +++ b/packages/tenderly-hardhat/src/tasks/verify.ts @@ -6,22 +6,31 @@ import { logger } from "../utils/logger"; import { PLUGIN_NAME } from "../constants"; import { ContractByName } from "../tenderly/types"; -task("tenderly:verify", "Verifies contracts on Tenderly based on the configuration in hardhat.config.js.") +task( + "tenderly:verify", + "Verifies contracts on Tenderly based on the configuration in hardhat.config.js.", +) .addVariadicPositionalParam( "contracts", - "Addresses and names of contracts that will be verified formatted like `ContractName1=0x... ContractName2=0x...`" + "Addresses and names of contracts that will be verified formatted like `ContractName1=0x... ContractName2=0x...`", ) .addOptionalParam( "libraries", - "Libraries that contracts will use formatted like `ContractName1=LibraryName1:0x...,LibraryName2:0x...#ContractName2=LibraryName3:0x...,LibraryName4:0x...`" + "Libraries that contracts will use formatted like `ContractName1=LibraryName1:0x...,LibraryName2:0x...#ContractName2=LibraryName3:0x...,LibraryName4:0x...`", ) .setAction(verifyContract); -async function verifyContract({ contracts, libraries }: any, hre: HardhatRuntimeEnvironment) { +async function verifyContract( + { contracts, libraries }: any, + hre: HardhatRuntimeEnvironment, +) { logger.info("Verification via tenderly:verify hardhat task is invoked."); if (contracts === undefined) { - throw new HardhatPluginError(PLUGIN_NAME, `At least one contract must be provided (ContractName=Address)`); + throw new HardhatPluginError( + PLUGIN_NAME, + `At least one contract must be provided (ContractName=Address)`, + ); } const formattedContracts: ContractByName[] = []; diff --git a/packages/tenderly-hardhat/src/tenderly/ethers.ts b/packages/tenderly-hardhat/src/tenderly/ethers.ts index 1af733e6..57a7bf0a 100644 --- a/packages/tenderly-hardhat/src/tenderly/ethers.ts +++ b/packages/tenderly-hardhat/src/tenderly/ethers.ts @@ -13,32 +13,33 @@ import { TdlyContract } from "./ethers/Contract"; export function wrapEthers( nativeEthers: typeof ethers & HardhatEthersHelpers, - tenderly: TenderlyPlugin + tenderly: TenderlyPlugin, ): typeof ethers & HardhatEthersHelpers { // Factory - nativeEthers.getContractFactoryFromArtifact = wrapGetContractFactoryFromArtifact( - nativeEthers.getContractFactoryFromArtifact, - tenderly - ) as typeof nativeEthers.getContractFactoryFromArtifact; + nativeEthers.getContractFactoryFromArtifact = + wrapGetContractFactoryFromArtifact( + nativeEthers.getContractFactoryFromArtifact, + tenderly, + ) as typeof nativeEthers.getContractFactoryFromArtifact; nativeEthers.getContractFactory = wrapGetContractFactory( nativeEthers.getContractFactory, - tenderly + tenderly, ) as typeof nativeEthers.getContractFactory; // Ethers's deployContract nativeEthers.deployContract = wrapDeployContract( nativeEthers.deployContract, - tenderly + tenderly, ) as typeof nativeEthers.deployContract; // Contract nativeEthers.getContractAtFromArtifact = wrapGetContractAtFromArtifact( nativeEthers.getContractAtFromArtifact, - tenderly + tenderly, ) as typeof nativeEthers.getContractAtFromArtifact; nativeEthers.getContractAt = wrapGetContractAt( nativeEthers.getContractAt, - tenderly + tenderly, ) as typeof nativeEthers.getContractAt; return nativeEthers; @@ -46,32 +47,36 @@ export function wrapEthers( export declare function getContractFactoryName( name: string, - signerOrOptions?: ethers.Signer | FactoryOptions + signerOrOptions?: ethers.Signer | FactoryOptions, ): Promise; export declare function getContractFactoryABI( abi: any[], bytecode: ethers.BytesLike, - signer?: ethers.Signer + signer?: ethers.Signer, ): Promise; function wrapGetContractFactory( func: typeof getContractFactoryName | typeof getContractFactoryABI, - tenderly: TenderlyPlugin + tenderly: TenderlyPlugin, ): typeof getContractFactoryName | typeof getContractFactoryABI { return async function ( nameOrAbi: string | any[], - bytecodeOrFactoryOptions?: (ethers.Signer | FactoryOptions) | ethers.BytesLike, - signer?: ethers.Signer + bytecodeOrFactoryOptions?: + | (ethers.Signer | FactoryOptions) + | ethers.BytesLike, + signer?: ethers.Signer, ): Promise { if (typeof nameOrAbi === "string") { const contractFactory = await (func as typeof getContractFactoryName)( nameOrAbi, - bytecodeOrFactoryOptions as ethers.Signer | FactoryOptions + bytecodeOrFactoryOptions as ethers.Signer | FactoryOptions, ); let libs; - const factoryOpts = bytecodeOrFactoryOptions as ethers.Signer | FactoryOptions; + const factoryOpts = bytecodeOrFactoryOptions as + | ethers.Signer + | FactoryOptions; if (factoryOpts !== undefined && "libraries" in factoryOpts) { libs = factoryOpts.libraries; } @@ -82,23 +87,23 @@ function wrapGetContractFactory( return (func as typeof getContractFactoryABI)( nameOrAbi, bytecodeOrFactoryOptions as ethers.BytesLike, - signer + signer, ); }; } export declare function deployContract( name: string, - signerOrOptions?: ethers.Signer | DeployContractOptions + signerOrOptions?: ethers.Signer | DeployContractOptions, ): Promise; function wrapDeployContract( func: typeof deployContract, - tenderly: TenderlyPlugin + tenderly: TenderlyPlugin, ): typeof deployContract { return async function ( name: string, - signerOrOptions?: ethers.Signer | DeployContractOptions + signerOrOptions?: ethers.Signer | DeployContractOptions, ): Promise { const contract = await func(name, signerOrOptions); @@ -107,18 +112,30 @@ function wrapDeployContract( libraries = signerOrOptions.libraries; } - return new TdlyContract(contract, tenderly, name, libraries) as unknown as ethers.Contract; + return new TdlyContract( + contract, + tenderly, + name, + libraries, + ) as unknown as ethers.Contract; }; } export declare function getContractAt( nameOrAbi: string | any[], address: string, - signer?: ethers.Signer + signer?: ethers.Signer, ): Promise; -function wrapGetContractAt(func: typeof getContractAt, tenderly: TenderlyPlugin): typeof getContractAt { - return async function (nameOrAbi: string | any[], address: string, signer?: ethers.Signer): Promise { +function wrapGetContractAt( + func: typeof getContractAt, + tenderly: TenderlyPlugin, +): typeof getContractAt { + return async function ( + nameOrAbi: string | any[], + address: string, + signer?: ethers.Signer, + ): Promise { if (typeof nameOrAbi === "string") { const contract = await func(nameOrAbi, address, signer); await tryToVerify(tenderly, nameOrAbi, contract); @@ -132,16 +149,16 @@ function wrapGetContractAt(func: typeof getContractAt, tenderly: TenderlyPlugin) export declare function getContractFactoryFromArtifact( artifact: Artifact, - signerOrOptions?: ethers.Signer | FactoryOptions + signerOrOptions?: ethers.Signer | FactoryOptions, ): Promise; function wrapGetContractFactoryFromArtifact( func: typeof getContractFactoryFromArtifact, - tenderly: TenderlyPlugin + tenderly: TenderlyPlugin, ): typeof getContractFactoryFromArtifact { return async function ( artifact: Artifact, - signerOrOptions?: ethers.Signer | FactoryOptions + signerOrOptions?: ethers.Signer | FactoryOptions, ): Promise { const contractFactory = await func(artifact, signerOrOptions); @@ -151,21 +168,30 @@ function wrapGetContractFactoryFromArtifact( libs = factoryOpts.libraries; } - return wrapContractFactory(contractFactory, tenderly, artifact.contractName, libs); + return wrapContractFactory( + contractFactory, + tenderly, + artifact.contractName, + libs, + ); }; } export declare function getContractAtFromArtifact( artifact: Artifact, address: string, - signer?: ethers.Signer + signer?: ethers.Signer, ): Promise; function wrapGetContractAtFromArtifact( func: typeof getContractAtFromArtifact, - tenderly: TenderlyPlugin + tenderly: TenderlyPlugin, ): typeof getContractAtFromArtifact { - return async function (artifact: Artifact, address: string, signer?: ethers.Signer): Promise { + return async function ( + artifact: Artifact, + address: string, + signer?: ethers.Signer, + ): Promise { const contract = await func(artifact, address, signer); await tryToVerify(tenderly, artifact.contractName, contract); @@ -177,19 +203,23 @@ function wrapContractFactory( contractFactory: ethers.ContractFactory, tenderly: TenderlyPlugin, name: string, - libraries?: Libraries + libraries?: Libraries, ): ethers.ContractFactory { contractFactory = new TdlyContractFactory( contractFactory, tenderly, name, - libraries + libraries, ) as unknown as ethers.ContractFactory; return contractFactory; } -async function tryToVerify(tenderly: TenderlyPlugin, name: string, contract: ethers.Contract) { +async function tryToVerify( + tenderly: TenderlyPlugin, + name: string, + contract: ethers.Contract, +) { await tenderly.verify({ name, address: await contract.getAddress(), diff --git a/packages/tenderly-hardhat/src/tenderly/ethers/Contract.ts b/packages/tenderly-hardhat/src/tenderly/ethers/Contract.ts index e2db1aad..069f5fb3 100644 --- a/packages/tenderly-hardhat/src/tenderly/ethers/Contract.ts +++ b/packages/tenderly-hardhat/src/tenderly/ethers/Contract.ts @@ -1,4 +1,4 @@ -import {Contract, ContractTransactionReceipt, ethers} from "ethers"; +import { Contract, ContractTransactionReceipt, ethers } from "ethers"; import { BigNumber } from "@ethersproject/bignumber"; import { Libraries } from "@nomicfoundation/hardhat-ethers/types"; @@ -13,7 +13,12 @@ export class TdlyContract { private tenderly: TenderlyPlugin; private libraries: Libraries | undefined; - constructor(nativeContract: ethers.Contract, tenderly: TenderlyPlugin, contractName: string, libs?: Libraries) { + constructor( + nativeContract: ethers.Contract, + tenderly: TenderlyPlugin, + contractName: string, + libs?: Libraries, + ) { this.contractName = contractName; this.nativeContract = nativeContract; this.tenderly = tenderly; @@ -26,19 +31,27 @@ export class TdlyContract { if (key === "deploymentTransaction") { const deploymentTransaction = nativeContract[key](); - if (deploymentTransaction === undefined || deploymentTransaction === null) { + if ( + deploymentTransaction === undefined || + deploymentTransaction === null + ) { return; } const wait = deploymentTransaction.wait; - deploymentTransaction.wait = async (confirmations?: number | undefined): Promise => { + deploymentTransaction.wait = async ( + confirmations?: number | undefined, + ): Promise => { const receipt = await wait(confirmations); if (receipt === undefined || receipt === null) { return null; } - if (receipt.contractAddress === undefined || receipt.contractAddress === null) { + if ( + receipt.contractAddress === undefined || + receipt.contractAddress === null + ) { return receipt; } await this._tdlyVerify(receipt.contractAddress); diff --git a/packages/tenderly-hardhat/src/tenderly/ethers/ContractFactory.ts b/packages/tenderly-hardhat/src/tenderly/ethers/ContractFactory.ts index 22e54e44..cc36f882 100644 --- a/packages/tenderly-hardhat/src/tenderly/ethers/ContractFactory.ts +++ b/packages/tenderly-hardhat/src/tenderly/ethers/ContractFactory.ts @@ -17,7 +17,7 @@ export class TdlyContractFactory { nativeContractFactory: ContractFactory, tenderly: TenderlyPlugin, contractName: string, - libs?: Libraries + libs?: Libraries, ) { this.nativeContractFactory = nativeContractFactory; this.tenderly = tenderly; @@ -42,12 +42,22 @@ export class TdlyContractFactory { public async deploy(...args: any[]): Promise { const contract = await this.nativeContractFactory.deploy(...args); - return new TdlyContract(contract as Contract, this.tenderly, this.contractName, this.libs) as unknown as Contract; + return new TdlyContract( + contract as Contract, + this.tenderly, + this.contractName, + this.libs, + ) as unknown as Contract; } public connect(signer: Signer) { const contractFactory = this.nativeContractFactory.connect(signer); - return new TdlyContractFactory(contractFactory, this.tenderly, this.contractName, this.libs); + return new TdlyContractFactory( + contractFactory, + this.tenderly, + this.contractName, + this.libs, + ); } } diff --git a/packages/tenderly-hardhat/src/tenderly/extender.ts b/packages/tenderly-hardhat/src/tenderly/extender.ts index 18b3d1fe..2350c6d1 100644 --- a/packages/tenderly-hardhat/src/tenderly/extender.ts +++ b/packages/tenderly-hardhat/src/tenderly/extender.ts @@ -1,7 +1,11 @@ import "@nomicfoundation/hardhat-ethers"; import { lazyObject } from "hardhat/plugins"; import { extendConfig, extendEnvironment } from "hardhat/config"; -import { HardhatRuntimeEnvironment, HttpNetworkConfig, HardhatConfig } from "hardhat/types"; +import { + HardhatRuntimeEnvironment, + HttpNetworkConfig, + HardhatConfig, +} from "hardhat/types"; import { HardhatEthersHelpers } from "@nomicfoundation/hardhat-ethers/types"; import { TenderlyService } from "tenderly"; import { logger as serviceLogger } from "tenderly/utils/logger"; @@ -36,10 +40,12 @@ export function setup() { serviceLogger.settings.minLevel = 1; // trace level } logger.info( - `Setting up hardhat-tenderly plugin. Log level of hardhat tenderly plugin set to: ${logger.settings.minLevel}` + `Setting up hardhat-tenderly plugin. Log level of hardhat tenderly plugin set to: ${logger.settings.minLevel}`, ); // serviceLogger is used here just for initialization, nothing else, it will be used in TenderlyService.ts - serviceLogger.info(`Log level of tenderly service set to: ${serviceLogger.settings.minLevel}`); + serviceLogger.info( + `Log level of tenderly service set to: ${serviceLogger.settings.minLevel}`, + ); const pjson = require("../../package.json"); logger.info("@tenderly/hardhat-tenderly version:", pjson.version); @@ -55,7 +61,9 @@ export function setup() { extendProvider(hre); populateNetworks(); if (process.env.AUTOMATIC_VERIFICATION_ENABLED === "true") { - logger.debug("Automatic verification is enabled, proceeding to extend ethers library."); + logger.debug( + "Automatic verification is enabled, proceeding to extend ethers library.", + ); extendEthers(hre); extendHardhatDeploy(hre); logger.debug("Wrapping ethers library finished."); @@ -79,7 +87,9 @@ extendConfig((resolvedConfig: HardhatConfig) => { const extendProvider = (hre: HardhatRuntimeEnvironment): void => { if (!isTenderlyNetworkConfig(hre.network.config)) { - logger.info(`Used network is not 'tenderly' so there is no extending of the provider.`); + logger.info( + `Used network is not 'tenderly' so there is no extending of the provider.`, + ); return; } @@ -87,7 +97,10 @@ const extendProvider = (hre: HardhatRuntimeEnvironment): void => { if (hre.network.config.url.includes("devnet")) { const devnetID = hre.network.config.url.split("/").pop(); hre.tenderly.network().setDevnetID(devnetID); - logger.info(`There is a devnet url in the '${hre.network.name}' network`, { devnetID }); + logger.info( + `There is a devnet url in the '${hre.network.name}' network`, + { devnetID }, + ); return; } const forkID = hre.network.config.url.split("/").pop(); @@ -102,11 +115,14 @@ const extendProvider = (hre: HardhatRuntimeEnvironment): void => { .then(async (_) => { hre.tenderly.setNetwork(tenderlyNetwork); const forkID = await hre.tenderly.network().getForkID(); - (hre.network.config as HttpNetworkConfig).url = `${TENDERLY_JSON_RPC_BASE_URL}/fork/${forkID ?? ""}`; + (hre.network.config as HttpNetworkConfig).url = + `${TENDERLY_JSON_RPC_BASE_URL}/fork/${forkID ?? ""}`; // hre.ethers.provider = new hre.ethers.BrowserProvider(hre.tenderly.network()); }) .catch((_) => { - logger.error(`Error happened while trying to initialize fork ${PLUGIN_NAME}. Check your tenderly configuration`); + logger.error( + `Error happened while trying to initialize fork ${PLUGIN_NAME}. Check your tenderly configuration`, + ); }); }; @@ -120,7 +136,8 @@ const populateNetworks = (): void => { NETWORK_NAME_CHAIN_ID_MAP[network.slug] = network.ethereum_network_id; if (network?.metadata?.slug !== undefined) { - NETWORK_NAME_CHAIN_ID_MAP[network.metadata.slug] = network.ethereum_network_id; + NETWORK_NAME_CHAIN_ID_MAP[network.metadata.slug] = + network.ethereum_network_id; } CHAIN_ID_NETWORK_NAME_MAP[network.ethereum_network_id] = network.slug; @@ -129,7 +146,10 @@ const populateNetworks = (): void => { NETWORK_NAME_CHAIN_ID_MAP[slug] = network.ethereum_network_id; } } - logger.silly("Obtained supported public networks: ", NETWORK_NAME_CHAIN_ID_MAP); + logger.silly( + "Obtained supported public networks: ", + NETWORK_NAME_CHAIN_ID_MAP, + ); }) .catch((_) => { logger.error("Error encountered while fetching public networks"); @@ -148,8 +168,8 @@ const extendEthers = (hre: HardhatRuntimeEnvironment): void => { hre.ethers, wrapEthers( hre.ethers as unknown as typeof ethers & HardhatEthersHelpers, - hre.tenderly - ) as unknown as typeof hre.ethers + hre.tenderly, + ) as unknown as typeof hre.ethers, ); } }; diff --git a/packages/tenderly-hardhat/src/tenderly/hardhat-deploy.ts b/packages/tenderly-hardhat/src/tenderly/hardhat-deploy.ts index f5cac49a..33daf9a8 100644 --- a/packages/tenderly-hardhat/src/tenderly/hardhat-deploy.ts +++ b/packages/tenderly-hardhat/src/tenderly/hardhat-deploy.ts @@ -1,17 +1,33 @@ -import { DeploymentsExtension, DeployOptions, DeployResult } from "hardhat-deploy/types"; +import { + DeploymentsExtension, + DeployOptions, + DeployResult, +} from "hardhat-deploy/types"; import { TenderlyPlugin } from "../type-extensions"; -export function wrapHHDeployments(deployments: DeploymentsExtension, tenderly: TenderlyPlugin) { +export function wrapHHDeployments( + deployments: DeploymentsExtension, + tenderly: TenderlyPlugin, +) { deployments.deploy = wrapDeploy(deployments.deploy, tenderly); return deployments; } -export declare function hhDeploy(name: string, options: DeployOptions): Promise; +export declare function hhDeploy( + name: string, + options: DeployOptions, +): Promise; -function wrapDeploy(deployFunc: typeof hhDeploy, tenderly: TenderlyPlugin): typeof hhDeploy { - return async function (name: string, options: DeployOptions): Promise { +function wrapDeploy( + deployFunc: typeof hhDeploy, + tenderly: TenderlyPlugin, +): typeof hhDeploy { + return async function ( + name: string, + options: DeployOptions, + ): Promise { const depResult = await deployFunc(name, options); await tenderly.verify({ name, diff --git a/packages/tenderly-hardhat/src/type-extensions.ts b/packages/tenderly-hardhat/src/type-extensions.ts index caaf5683..9603160a 100644 --- a/packages/tenderly-hardhat/src/type-extensions.ts +++ b/packages/tenderly-hardhat/src/type-extensions.ts @@ -89,7 +89,9 @@ export interface TenderlyPlugin { * ] * }); */ - verifyMultiCompilerAPI: (request: TenderlyVerifyContractsRequest) => Promise; + verifyMultiCompilerAPI: ( + request: TenderlyVerifyContractsRequest, + ) => Promise; /** * * @description @@ -151,7 +153,7 @@ export interface TenderlyPlugin { request: TenderlyVerifyContractsRequest, tenderlyProject: string, username: string, - forkID: string + forkID: string, ) => Promise; /** * @@ -214,8 +216,8 @@ export interface TenderlyPlugin { request: TenderlyVerifyContractsRequest, tenderlyProject: string, username: string, - devnetID: string - ): Promise + devnetID: string, + ): Promise; /** * * @description @@ -320,7 +322,7 @@ export interface TenderlyPlugin { request: TenderlyForkContractUploadRequest, tenderlyProject: string, username: string, - forkID: string + forkID: string, ) => Promise; /** * * @description Persisting contract deployment data needed for verification purposes using hre. @@ -370,7 +372,11 @@ export interface TenderlyPlugin { * ] * }, "project", "tenderly"); */ - pushAPI: (request: TenderlyContractUploadRequest, tenderlyProject: string, username: string) => Promise; + pushAPI: ( + request: TenderlyContractUploadRequest, + tenderlyProject: string, + username: string, + ) => Promise; /** * * @deprecated * @description @@ -397,14 +403,14 @@ declare module "hardhat/types/runtime" { method: string; params?: any[]; }, - callback: (error: any, response: any) => void + callback: (error: any, response: any) => void, ) => void; verify: (...contracts: any[]) => Promise; verifyAPI: ( request: TenderlyForkContractUploadRequest, tenderlyProject: string, username: string, - forkID: string + forkID: string, ) => Promise; resetFork: () => string | undefined; getHead: () => string | undefined; diff --git a/packages/tenderly-hardhat/src/utils/util.ts b/packages/tenderly-hardhat/src/utils/util.ts index 4c34cfa4..d2d78aa4 100644 --- a/packages/tenderly-hardhat/src/utils/util.ts +++ b/packages/tenderly-hardhat/src/utils/util.ts @@ -32,7 +32,7 @@ import { logger } from "./logger"; export const makeVerifyContractsRequest = async ( hre: HardhatRuntimeEnvironment, flatContracts: ContractByName[], - platformID?: string + platformID?: string, ): Promise => { logger.info("Processing data needed for verification."); @@ -46,7 +46,7 @@ export const makeVerifyContractsRequest = async ( } catch (err) { // TODO(dusan): See how to wrap errors, don't return errors like this logger.error( - `Error while trying to get compilation job for contract '${flatContract.name}'. The provided contract name probably doesn't exist or is mistyped.` + `Error while trying to get compilation job for contract '${flatContract.name}'. The provided contract name probably doesn't exist or is mistyped.`, ); throw err; } @@ -54,30 +54,39 @@ export const makeVerifyContractsRequest = async ( const networkName = hre.hardhatArguments.network; if (networkName === undefined) { logger.error( - `Error in ${PLUGIN_NAME}: Please provide a network via the hardhat --network argument or directly in the contract` + `Error in ${PLUGIN_NAME}: Please provide a network via the hardhat --network argument or directly in the contract`, ); return null; } logger.trace("Found network is:", networkName); let chainId; - if (isTenderlyNetworkConfig(hre.config.networks[networkName]) && platformID !== undefined) { + if ( + isTenderlyNetworkConfig(hre.config.networks[networkName]) && + platformID !== undefined + ) { chainId = platformID; } else if (hre.network?.config?.chainId !== undefined) { chainId = hre.network.config.chainId.toString(); - } else if (NETWORK_NAME_CHAIN_ID_MAP[networkName.toLowerCase()] !== undefined) { + } else if ( + NETWORK_NAME_CHAIN_ID_MAP[networkName.toLowerCase()] !== undefined + ) { chainId = NETWORK_NAME_CHAIN_ID_MAP[networkName.toLowerCase()].toString(); } logger.trace(`ChainId for network '${networkName}' is ${chainId}`); if (chainId === undefined) { logger.error( - `Error in ${PLUGIN_NAME}: Couldn't identify network. Please provide a chainId in the network config object` + `Error in ${PLUGIN_NAME}: Couldn't identify network. Please provide a chainId in the network config object`, ); return null; } - const compiler = await insertLibraries(hre, job.getSolcConfig(), flatContract.libraries); + const compiler = await insertLibraries( + hre, + job.getSolcConfig(), + flatContract.libraries, + ); contracts.push({ contractToVerify: flatContract.name, @@ -102,12 +111,13 @@ export const makeVerifyContractsRequest = async ( async function extractSources( hre: HardhatRuntimeEnvironment, contractToVerify: string, - job: CompilationJob + job: CompilationJob, ): Promise> { const sources: Record = {}; logger.info("Extracting sources from compilation job."); - const mainArtifact: Artifact = hre.artifacts.readArtifactSync(contractToVerify); + const mainArtifact: Artifact = + hre.artifacts.readArtifactSync(contractToVerify); for (const file of job.getResolvedFiles()) { let contractName = CONTRACT_NAME_PLACEHOLDER; // Only the contract to verify should have its name extracted since we need to attach a network to it. @@ -127,7 +137,7 @@ async function extractSources( async function insertLibraries( hre: HardhatRuntimeEnvironment, originalCompiler: SolcConfig, - libraries: Libraries | undefined + libraries: Libraries | undefined, ): Promise { // we need to copy the compiler in order to not modify the hardhat's compiler from the settings const copiedCompiler: SolcConfig = { @@ -140,20 +150,26 @@ async function insertLibraries( return copiedCompiler; } - if (copiedCompiler.settings.libraries !== undefined && copiedCompiler.settings.libraries !== null) { + if ( + copiedCompiler.settings.libraries !== undefined && + copiedCompiler.settings.libraries !== null + ) { throw new Error( - `There are multiple definitions of libraries the contract should use. One is defined in the verify request and the other as an compiler config override. Please remove one of them.` + `There are multiple definitions of libraries the contract should use. One is defined in the verify request and the other as an compiler config override. Please remove one of them.`, ); } copiedCompiler.settings.libraries = {}; for (const [libName, libAddress] of Object.entries(libraries)) { const libArtifact: Artifact = hre.artifacts.readArtifactSync(libName); - if (copiedCompiler.settings.libraries[libArtifact.sourceName] === undefined) { + if ( + copiedCompiler.settings.libraries[libArtifact.sourceName] === undefined + ) { copiedCompiler.settings.libraries[libArtifact.sourceName] = {}; } - copiedCompiler.settings.libraries[libArtifact.sourceName][libName] = libAddress; + copiedCompiler.settings.libraries[libArtifact.sourceName][libName] = + libAddress; } return copiedCompiler; @@ -187,7 +203,9 @@ async function repackLibraries(compiler: SolcConfig): Promise { return compiler; } const libraries: any = {}; - for (const [fileName, libVal] of Object.entries(compiler.settings.libraries)) { + for (const [fileName, libVal] of Object.entries( + compiler.settings.libraries, + )) { if (libraries[fileName] === undefined) { libraries[fileName] = { addresses: {} }; } @@ -202,7 +220,7 @@ async function repackLibraries(compiler: SolcConfig): Promise { export const getCompilationJob = async ( hre: HardhatRuntimeEnvironment, - contractName: string + contractName: string, ): Promise => { logger.trace("Getting compilation job for contract:", contractName); @@ -219,11 +237,16 @@ export const getCompilationJob = async ( }); }; -async function getDependencyGraph(hre: HardhatRuntimeEnvironment): Promise { +async function getDependencyGraph( + hre: HardhatRuntimeEnvironment, +): Promise { const sourcePaths = await hre.run(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS); - const sourceNames: string[] = await hre.run(TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES, { - sourcePaths, - }); + const sourceNames: string[] = await hre.run( + TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES, + { + sourcePaths, + }, + ); return hre.run(TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH, { sourceNames, }); @@ -232,7 +255,7 @@ async function getDependencyGraph(hre: HardhatRuntimeEnvironment): Promise { logger.debug("Obtaining compiler data from contracts."); @@ -246,9 +269,19 @@ export const getCompilerDataFromContracts = ( } logger.trace("Obtaining compiler data from contract:", mainContract.name); - const contractConfig = newCompilerConfig(hhConfig, contract.sourcePath, contract.compiler?.version); - if (config !== null && config !== undefined && !compareConfigs(contractConfig, config)) { - logger.error(`Error in ${PLUGIN_NAME}: Different compiler versions provided in same request`); + const contractConfig = newCompilerConfig( + hhConfig, + contract.sourcePath, + contract.compiler?.version, + ); + if ( + config !== null && + config !== undefined && + !compareConfigs(contractConfig, config) + ) { + logger.error( + `Error in ${PLUGIN_NAME}: Different compiler versions provided in same request`, + ); throw new Error("Compiler version mismatch"); } else { config = contractConfig; @@ -263,7 +296,7 @@ export const getCompilerDataFromContracts = ( export const getContracts = async ( hre: HardhatRuntimeEnvironment, - flatContracts: ContractByName[] + flatContracts: ContractByName[], ): Promise => { logger.debug("Processing contracts from the artifacts/ directory."); @@ -286,7 +319,10 @@ export const getContracts = async ( }, sources: {}, }; - logger.trace("Extracted compiler version is:", metadata.defaultCompiler.version); + logger.trace( + "Extracted compiler version is:", + metadata.defaultCompiler.version, + ); data._resolvedFiles.forEach((resolvedFile: any, _: any) => { const sourcePath: string = resolvedFile.sourceName; @@ -341,9 +377,15 @@ export const getContracts = async ( requestContracts.push(contractToPush); } - logger.silly("Finished processing contracts from the artifacts/ folder:", requestContracts); + logger.silly( + "Finished processing contracts from the artifacts/ folder:", + requestContracts, + ); - logger.silly("Finished processing contracts from the artifacts/ folder:", requestContracts); + logger.silly( + "Finished processing contracts from the artifacts/ folder:", + requestContracts, + ); return requestContracts; }; @@ -352,7 +394,7 @@ export const resolveDependencies = ( dependencyData: any, sourcePath: string, metadata: Metadata, - visited: Record + visited: Record, ): void => { if (visited[sourcePath]) { return; @@ -360,16 +402,26 @@ export const resolveDependencies = ( visited[sourcePath] = true; - dependencyData._dependenciesPerFile.get(sourcePath).forEach((resolvedDependency: any, _: any) => { - resolveDependencies(dependencyData, resolvedDependency.sourceName, metadata, visited); - metadata.sources[resolvedDependency.sourceName] = { - content: resolvedDependency.content.rawContent, - versionPragma: resolvedDependency.content.versionPragmas[0], - }; - }); + dependencyData._dependenciesPerFile + .get(sourcePath) + .forEach((resolvedDependency: any, _: any) => { + resolveDependencies( + dependencyData, + resolvedDependency.sourceName, + metadata, + visited, + ); + metadata.sources[resolvedDependency.sourceName] = { + content: resolvedDependency.content.rawContent, + versionPragma: resolvedDependency.content.versionPragmas[0], + }; + }); }; -export const compareConfigs = (originalConfig: TenderlyContractConfig, newConfig: TenderlyContractConfig): boolean => { +export const compareConfigs = ( + originalConfig: TenderlyContractConfig, + newConfig: TenderlyContractConfig, +): boolean => { if (originalConfig.compiler_version !== newConfig.compiler_version) { return false; } @@ -388,15 +440,20 @@ export const compareConfigs = (originalConfig: TenderlyContractConfig, newConfig export const newCompilerConfig = ( config: HardhatConfig, sourcePath?: string, - contractCompiler?: string + contractCompiler?: string, ): TenderlyContractConfig => { - if (sourcePath !== undefined && config.solidity.overrides[sourcePath] !== undefined) { + if ( + sourcePath !== undefined && + config.solidity.overrides[sourcePath] !== undefined + ) { logger.trace("There is a compiler config override for:", sourcePath); return { compiler_version: config.solidity.overrides[sourcePath].version, - optimizations_used: config.solidity.overrides[sourcePath].settings.optimizer.enabled, - optimizations_count: config.solidity.overrides[sourcePath].settings.optimizer.runs, + optimizations_used: + config.solidity.overrides[sourcePath].settings.optimizer.enabled, + optimizations_count: + config.solidity.overrides[sourcePath].settings.optimizer.runs, evm_version: config.solidity.overrides[sourcePath].settings.evmVersion, debug: config.solidity.overrides[sourcePath].settings.debug, }; @@ -418,8 +475,15 @@ export const newCompilerConfig = ( }; }; -export const extractCompilerVersion = (config: HardhatConfig, sourcePath?: string, versionPragma?: string): string => { - if (sourcePath !== undefined && config.solidity.overrides[sourcePath] !== undefined) { +export const extractCompilerVersion = ( + config: HardhatConfig, + sourcePath?: string, + versionPragma?: string, +): string => { + if ( + sourcePath !== undefined && + config.solidity.overrides[sourcePath] !== undefined + ) { return config.solidity.overrides[sourcePath].version; } if (versionPragma !== undefined) { @@ -454,11 +518,16 @@ export const isTenderlyNetworkConfig = (nw: NetworkConfig): boolean => { return regex.test(nw.url); }; -function isHttpNetworkConfig(config: NetworkConfig): config is HttpNetworkConfig { +function isHttpNetworkConfig( + config: NetworkConfig, +): config is HttpNetworkConfig { return (config as HttpNetworkConfig).url !== undefined; } -const determineCompilerConfig = (compilers: SolcConfig[], contractCompiler: string): TenderlyContractConfig => { +const determineCompilerConfig = ( + compilers: SolcConfig[], + contractCompiler: string, +): TenderlyContractConfig => { for (const compiler of compilers) { if (compareVersions(compiler.version, contractCompiler)) { logger.trace("Provided compiler matched the version: ", compiler.version); @@ -474,7 +543,7 @@ const determineCompilerConfig = (compilers: SolcConfig[], contractCompiler: stri } logger.trace( - "Couldn't find the provided compiler among compilers in the configuration, returning the configuration of the first one" + "Couldn't find the provided compiler among compilers in the configuration, returning the configuration of the first one", ); return { @@ -486,7 +555,10 @@ const determineCompilerConfig = (compilers: SolcConfig[], contractCompiler: stri }; }; -const compareVersions = (compilerVersion: string, contractVersionPragma: string): boolean => { +const compareVersions = ( + compilerVersion: string, + contractVersionPragma: string, +): boolean => { switch (contractVersionPragma[0]) { case "^": return checkGTEVersion(compilerVersion, contractVersionPragma.slice(1)); @@ -528,7 +600,10 @@ const compareVersions = (compilerVersion: string, contractVersionPragma: string) return false; }; -const checkGTEVersion = (compilerVersion: string, contractVersionPragma: string) => { +const checkGTEVersion = ( + compilerVersion: string, + contractVersionPragma: string, +) => { const compilerVersionSplit = compilerVersion.split("."); const contractVersionSplit = contractVersionPragma.split("."); for (let i = 0; i < compilerVersionSplit.length; i++) { @@ -543,7 +618,10 @@ const checkGTEVersion = (compilerVersion: string, contractVersionPragma: string) return true; }; -const checkGTVersion = (compilerVersion: string, contractVersionPragma: string) => { +const checkGTVersion = ( + compilerVersion: string, + contractVersionPragma: string, +) => { const compilerVersionSplit = compilerVersion.split("."); const contractVersionSplit = contractVersionPragma.split("."); for (let i = 0; i < compilerVersionSplit.length; i++) { @@ -559,16 +637,22 @@ const checkGTVersion = (compilerVersion: string, contractVersionPragma: string) }; // ------------------------------------------------------------------------------------ -const isGetter = (x: any, name: string): any => ((Object.getOwnPropertyDescriptor(x, name) !== null || {}) as any).get; -const isFunction = (x: any, name: string): boolean => typeof x[name] === "function"; +const isGetter = (x: any, name: string): any => + ((Object.getOwnPropertyDescriptor(x, name) !== null || {}) as any).get; +const isFunction = (x: any, name: string): boolean => + typeof x[name] === "function"; const deepFunctions = (x: any): string[] => { if (x && x !== Object.prototype) { return Object.getOwnPropertyNames(x) - .filter((name: string) => isGetter(x, name) !== null || isFunction(x, name)) + .filter( + (name: string) => isGetter(x, name) !== null || isFunction(x, name), + ) .concat(deepFunctions(Object.getPrototypeOf(x)) ?? []); } return []; }; const distinctDeepFunctions = (x: any) => Array.from(new Set(deepFunctions(x))); export const classFunctions = (x: any) => - distinctDeepFunctions(x).filter((name: string) => name !== "constructor" && name.indexOf("__") === -1); + distinctDeepFunctions(x).filter( + (name: string) => name !== "constructor" && name.indexOf("__") === -1, + );