UNPKG

hardhat-gas-reporter

Version:
376 lines 16.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateTerminalTextTable = void 0; const chalk_1 = __importDefault(require("chalk")); const lodash_1 = __importDefault(require("lodash")); const cli_table3_1 = __importDefault(require("cli-table3")); const units_1 = require("@ethersproject/units"); const constants_1 = require("../../constants"); const ui_1 = require("../../utils/ui"); /** * Generates a gas statistics text table formatted for terminal or file. * Based on Alan Lu's (github.com/cag) stats for Gnosis * @param {HardhatRuntimeEnvironment} hre * @param {GasData} data * @param {GasReporterOptions} options * @param {string} string */ function generateTerminalTextTable(hre, data, options, toolchain) { // Default cols (without L2) let numberOfCols = 7; let blockLimitColumnWidth = 2; let deploymentsTitleSpacerWidth = 2; let contractTitleSpacerWidth = 5; let executionGasAverageTitle = "Avg"; let calldataGasAverageTitle = ""; let optionalColor; if (options.noColors || options.outputFile !== undefined) { chalk_1.default.level = 0; } else { chalk_1.default.level = 1; } if (options.darkMode) { optionalColor = chalk_1.default.cyan; } else { optionalColor = chalk_1.default.bold; } if (options.L2 !== undefined) { numberOfCols = 8; blockLimitColumnWidth = 3; deploymentsTitleSpacerWidth = 3; contractTitleSpacerWidth = 6; executionGasAverageTitle = "L2 Avg (Exec)"; if (options.L2 === "optimism" || options.L2 === "base") { calldataGasAverageTitle = "L1 Avg (Data)"; } if (options.L2 === "arbitrum") { calldataGasAverageTitle = "L1 Avg (Bytes)"; } } // eslint-disable-next-line const emptyRow = [{ colSpan: numberOfCols, content: "" }]; // --------------------------------------------------------------------------------------------- // Methods: section assembly // --------------------------------------------------------------------------------------------- const methodRows = []; const addedContracts = []; lodash_1.default.forEach(data.methods, (method) => { if (!method) return; // Contracts name row if (!addedContracts.includes(method.contract) && method.gasData.length > 0) { addedContracts.push(method.contract); const contractNameSection = { row: [ { hAlign: "left", colSpan: 2, content: `${optionalColor(method.contract)}` }, { hAlign: "left", colSpan: contractTitleSpacerWidth, content: "" } ], contractName: method.contract, methodName: "0" }; methodRows.push(contractNameSection); } const stats = {}; if (method.gasData.length > 0) { stats.executionGasAverage = (0, units_1.commify)(method.executionGasAverage); stats.cost = (method.cost === undefined) ? chalk_1.default.grey("-") : method.cost; // Also writes dash when average is zero stats.calldataGasAverage = (method.calldataGasAverage) ? (0, units_1.commify)(method.calldataGasAverage) : chalk_1.default.grey("-"); if (options.trackGasDeltas) { stats.executionGasAverage = (0, ui_1.renderWithGasDelta)(stats.executionGasAverage, method.executionGasAverageDelta || 0, true); stats.calldataGasAverage = (0, ui_1.renderWithGasDelta)(stats.calldataGasAverage, method.calldataGasAverageDelta || 0, true); } } else { stats.executionGasAverage = chalk_1.default.grey("-"); stats.cost = chalk_1.default.grey("-"); } if ((0, ui_1.costIsBelowPrecision)(stats.cost, options)) { stats.cost = chalk_1.default.magenta.bold(constants_1.UNICODE_TRIANGLE); } if (method.min && method.max) { const uniform = (method.min === method.max); let min = chalk_1.default.cyan((0, units_1.commify)(method.min)); let max = chalk_1.default.red((0, units_1.commify)(method.max)); if (options.trackGasDeltas) { min = (0, ui_1.renderWithGasDelta)(min, method.minDelta || 0, true); max = (0, ui_1.renderWithGasDelta)(max, method.maxDelta || 0, true); } stats.min = uniform ? chalk_1.default.grey("-") : min; stats.max = uniform ? chalk_1.default.grey("-") : max; } const fnName = options.showMethodSig ? method.fnSig : method.method; const indented = (method.isCall) ? (0, ui_1.indentTextWithSymbol)(fnName, chalk_1.default.magenta.bold(constants_1.UNICODE_CIRCLE)) : (0, ui_1.indentText)(fnName); if (options.showUncalledMethods || method.numberOfCalls > 0) { const row = []; row.push({ hAlign: "left", colSpan: 2, content: indented }); row.push({ hAlign: "right", colSpan: 1, content: stats.min }); row.push({ hAlign: "right", colSpan: 1, content: stats.max }); row.push({ hAlign: "right", colSpan: 1, content: stats.executionGasAverage }); if (options.L2 !== undefined) { row.push({ hAlign: "right", colSpan: 1, content: stats.calldataGasAverage }); } row.push({ hAlign: "right", colSpan: 1, content: method.numberOfCalls }); row.push({ hAlign: "right", colSpan: 1, content: chalk_1.default.green(stats.cost.toString()) }); const section = { row, contractName: method.contract, methodName: fnName }; methodRows.push(section); } }); // --------------------------------------------------------------------------------------------- // Deployments: section assembly // --------------------------------------------------------------------------------------------- const deployRows = []; // Alphabetize contract names data.deployments.sort((a, b) => a.name.localeCompare(b.name)); data.deployments.forEach(deployment => { const stats = {}; if (deployment.gasData.length === 0) return; stats.cost = (deployment.cost === undefined) ? chalk_1.default.grey("-") : deployment.cost; if ((0, ui_1.costIsBelowPrecision)(stats.cost, options)) { stats.cost = chalk_1.default.magenta.bold(constants_1.UNICODE_TRIANGLE); } stats.executionGasAverage = (0, units_1.commify)(deployment.executionGasAverage); stats.calldataGasAverage = (deployment.calldataGasAverage === undefined) ? "" : (0, units_1.commify)(deployment.calldataGasAverage); if (options.trackGasDeltas) { stats.executionGasAverage = (0, ui_1.renderWithGasDelta)(stats.executionGasAverage, deployment.executionGasAverageDelta || 0, true); stats.calldataGasAverage = (0, ui_1.renderWithGasDelta)(stats.calldataGasAverage, deployment.calldataGasAverageDelta || 0, true); } if (deployment.min && deployment.max) { const uniform = (deployment.min === deployment.max); let min = chalk_1.default.cyan((0, units_1.commify)(deployment.min)); let max = chalk_1.default.red((0, units_1.commify)(deployment.max)); if (options.trackGasDeltas) { min = (0, ui_1.renderWithGasDelta)(min, deployment.minDelta || 0, true); max = (0, ui_1.renderWithGasDelta)(max, deployment.maxDelta || 0, true); } stats.min = uniform ? chalk_1.default.grey("-") : min; stats.max = uniform ? chalk_1.default.grey("-") : max; } const section = []; section.push({ hAlign: "left", colSpan: 2, content: chalk_1.default.bold(deployment.name) }); section.push({ hAlign: "right", colSpan: 1, content: stats.min }); section.push({ hAlign: "right", colSpan: 1, content: stats.max }); section.push({ hAlign: "right", colSpan: 1, content: stats.executionGasAverage }); if (options.L2 !== undefined) { section.push({ hAlign: "right", colSpan: 1, content: stats.calldataGasAverage }); } section.push({ hAlign: "right", colSpan: 1, content: `${deployment.percent} %` }); section.push({ hAlign: "right", colSpan: 1, content: chalk_1.default.green(stats.cost.toString()) }); deployRows.push(section); }); // --------------------------------------------------------------------------------------------- // Headers: section assembly // --------------------------------------------------------------------------------------------- // Configure indentation for RTD const leftPad = options.rst ? " " : ""; // Format table const table = new cli_table3_1.default({ style: { head: [], border: [], "padding-left": 2, "padding-right": 2 }, colWidths: [numberOfCols], chars: { mid: "·", "top-mid": "|", "left-mid": `${leftPad}·`, "mid-mid": "|", "right-mid": "·", left: `${leftPad}|`, "top-left": `${leftPad}·`, "top-right": "·", "bottom-left": `${leftPad}·`, "bottom-right": "·", middle: "·", top: "·", bottom: "·", "bottom-mid": "|" } }); const title = [ { hAlign: "left", colSpan: numberOfCols, content: chalk_1.default.green.bold(`Solidity and Network Configuration`) } ]; // ============ // SOLC CONFIG // ============ // Format and load methods metrics const solcConfig = [ { hAlign: "left", colSpan: 2, content: chalk_1.default.cyan(`Solidity: ${options.solcInfo.version}`) }, { hAlign: "left", colSpan: 1, content: chalk_1.default.cyan(`Optim: ${options.solcInfo.optimizer}`) }, { hAlign: "left", colSpan: 1, content: chalk_1.default.cyan(`Runs: ${options.solcInfo.runs}`) }, { hAlign: "left", colSpan: 1, content: chalk_1.default.cyan(`viaIR: ${options.solcInfo.viaIR.toString()}`) }, { hAlign: "center", colSpan: blockLimitColumnWidth, content: chalk_1.default.cyan(`Block: ${(0, units_1.commify)(options.blockGasLimit)} gas`) } ]; // ============== // NETWORK CONFIG // ============== let networkConfig = []; const opStackConfig = []; if (options.tokenPrice && options.gasPrice) { const { l1gwei, l2gwei, l1gweiNote, l2gweiNote, l1GweiBlobBaseFee, network, rate, currency, token } = (0, ui_1.getCommonTableVals)(options); networkConfig.push({ hAlign: "left", colSpan: 2, content: chalk_1.default.cyan(`Network: ${network}`) }); networkConfig.push({ hAlign: "left", colSpan: 2, content: chalk_1.default.cyan(`L1: ${l1gwei} gwei ${l1gweiNote}`) }); if (options.L2 !== undefined) { networkConfig.push({ hAlign: "left", colSpan: 2, content: chalk_1.default.cyan(`L2: ${l2gwei} gwei ${l2gweiNote}`) }); } else { networkConfig.push({ colSpan: 1, content: " " }); } networkConfig.push({ hAlign: "center", colSpan: 2, content: chalk_1.default.magenta(`${rate} ${currency}/${token}`) }); if (options.L2 === "optimism" || options.L2 === "base") { opStackConfig.push({ colSpan: 2, content: " " }); opStackConfig.push({ hAlign: "left", colSpan: 2, content: chalk_1.default.cyan(`L1: ${l1GweiBlobBaseFee} gwei (blobBaseFee)`) }); opStackConfig.push({ hAlign: "left", colSpan: 2, content: chalk_1.default.cyan(`Base Fee Scalar: ${options.opStackBaseFeeScalar}`) }); opStackConfig.push({ hAlign: "left", colSpan: 2, content: chalk_1.default.cyan(`Blob Fee Scalar: ${options.opStackBlobBaseFeeScalar}`) }); } } else { networkConfig = [ { hAlign: "left", colSpan: numberOfCols, content: chalk_1.default.green.bold("Methods") } ]; } // =============== // METHODS HEADER // =============== const methodsHeader = []; methodsHeader.push({ hAlign: "left", colSpan: 2, content: chalk_1.default.green.bold("Contracts / Methods") }); methodsHeader.push({ hAlign: "left", colSpan: 1, content: chalk_1.default.bold("Min") }); methodsHeader.push({ hAlign: "left", colSpan: 1, content: chalk_1.default.bold("Max") }); methodsHeader.push({ hAlign: "left", colSpan: 1, content: chalk_1.default.bold(executionGasAverageTitle) }); if (options.L2 !== undefined) { methodsHeader.push({ hAlign: "left", colSpan: 1, content: chalk_1.default.bold(calldataGasAverageTitle) }); } methodsHeader.push({ hAlign: "left", colSpan: 1, content: chalk_1.default.bold("# calls") }); methodsHeader.push({ hAlign: "left", colSpan: 1, content: chalk_1.default.bold(`${options.currency.toLowerCase()} (avg)`) }); // =============== // SYMBOL KEY // =============== const { intrinsicMsg, nonZeroMsg } = (0, ui_1.getCommonTableVals)(options); const keyTitle = [{ hAlign: "left", colSpan: numberOfCols, content: chalk_1.default.green.bold("Key") }]; const keyCall = [{ hAlign: "left", colSpan: numberOfCols, content: `${chalk_1.default.magenta.bold(constants_1.UNICODE_CIRCLE)} ${intrinsicMsg}` }]; const keyAir = [{ hAlign: "left", colSpan: numberOfCols, content: `${chalk_1.default.magenta.bold(constants_1.UNICODE_TRIANGLE)} ${nonZeroMsg}` }]; const keyToolchain = [{ hAlign: "left", colSpan: numberOfCols, content: `${chalk_1.default.magenta("Toolchain:")} ${toolchain}` }]; // --------------------------------------------------------------------------------------------- // Final table assembly // --------------------------------------------------------------------------------------------- table.push(title); table.push(solcConfig); table.push(networkConfig); if (opStackConfig.length > 0) { table.push(opStackConfig); } table.push(methodsHeader); methodRows.sort((a, b) => { const contractName = a.contractName.localeCompare(b.contractName); const methodName = a.methodName.localeCompare(b.methodName); return contractName || methodName; }); const rows = methodRows.map(val => val.row); rows.forEach(row => table.push(row)); if (deployRows.length) { const deploymentsSubtitle = [ { hAlign: "left", colSpan: 3, content: chalk_1.default.green.bold("Deployments") }, { hAlign: "right", colSpan: deploymentsTitleSpacerWidth, content: "" }, { hAlign: "left", colSpan: 1, content: chalk_1.default.bold(`% of limit`) }, { hAlign: "left", colSpan: 1, content: "" } ]; table.push(deploymentsSubtitle); deployRows.forEach((row) => table.push(row)); } table.push(keyTitle); table.push(keyCall); table.push(keyAir); table.push(keyToolchain); return table.toString(); } exports.generateTerminalTextTable = generateTerminalTextTable; //# sourceMappingURL=terminal.js.map