hardhat
Version:
Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.
113 lines (99 loc) • 3.09 kB
text/typescript
import chalk from "chalk";
/**
* Converts an internal FQN (e.g. `"project/contracts/Foo.sol:Foo"` or
* `"npm/@oz/contracts@5.0.0/token/ERC20.sol:ERC20"`) to its user-friendly
* form by stripping the `project/` prefix or npm version segment.
*/
export function getUserFqn(inputFqn: string): string {
if (inputFqn.startsWith("project/")) {
return inputFqn.slice("project/".length);
}
if (inputFqn.startsWith("npm/")) {
const withoutPrefix = inputFqn.slice("npm/".length);
// Match "<pkg>@<version>/<rest>", where <pkg> may be scoped (@scope/pkg)
const match = withoutPrefix.match(/^(@?[^@/]+(?:\/[^@/]+)*)@[^/]+\/(.*)$/);
if (match !== null) {
return `${match[1]}/${match[2]}`;
}
return withoutPrefix;
}
return inputFqn;
}
/**
* Extracts the function name from a Solidity function signature
* (e.g. `"transfer(address,uint256)"` → `"transfer"`).
*/
export function getFunctionName(signature: string): string {
return signature.split("(")[0];
}
/**
* Builds a deterministic string key for grouping gas measurements by
* (contractFqn, proxyChain). Uses null-byte separators to avoid collisions.
*/
export function makeGroupKey(
contractFqn: string,
proxyChain: string[],
): string {
if (proxyChain.length === 0) {
return contractFqn;
}
return contractFqn + "\0" + proxyChain.join("\0");
}
/**
* Returns a human-readable proxy label like `"(via Proxy2 → Proxy)"`,
* or `undefined` for direct calls. Strips the last element (the
* implementation) and converts internal FQNs to user-friendly format.
*/
export function getProxyLabel(proxyChain: string[]): string | undefined {
const proxies = proxyChain.slice(0, -1).map(getUserFqn);
if (proxies.length === 0) {
return undefined;
}
return `(via ${proxies.join(" → ")})`;
}
/**
* Returns a display key for a contract entry, appending the proxy label
* when the call went through a proxy chain. Used for table headers and
* JSON object keys.
*/
export function getDisplayKey(userFqn: string, proxyChain: string[]): string {
const label = getProxyLabel(proxyChain);
if (label === undefined) {
return userFqn;
}
return `${userFqn} ${label}`;
}
export function avg(values: number[]): number {
return values.reduce((a, c) => a + c, 0) / values.length;
}
export function median(values: number[]): number {
const sorted = [...values].sort((a, b) => a - b);
const mid = Math.floor(sorted.length / 2);
return sorted.length % 2 === 1
? sorted[mid]
: (sorted[mid - 1] + sorted[mid]) / 2;
}
export function formatSectionHeader(
sectionName: string,
{
changedLength,
addedLength,
removedLength,
}: {
changedLength: number;
addedLength: number;
removedLength: number;
},
): string {
const parts: string[] = [];
if (changedLength > 0) {
parts.push(`${changedLength} changed`);
}
if (addedLength > 0) {
parts.push(`${addedLength} added`);
}
if (removedLength > 0) {
parts.push(`${removedLength} removed`);
}
return `${sectionName}: ${chalk.gray(parts.join(", "))}`;
}