hardhat
Version:
Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.
152 lines • 5.65 kB
JavaScript
import { LogKind, CallKind, IncludeTraces } from "@nomicfoundation/edr";
import { bytesToHexString } from "@nomicfoundation/hardhat-utils/hex";
export function verbosityToIncludeTraces(verbosity) {
if (verbosity >= 4) {
return IncludeTraces.All;
}
else if (verbosity >= 3) {
return IncludeTraces.Failing;
}
return IncludeTraces.None;
}
export function formatTraces(traces, prefix, colorizer) {
const lines = traces.map((trace) => formatTrace(trace, colorizer));
const formattedTraces = formatNestedArray(lines, prefix);
// Remove the trailing newline
return formattedTraces.slice(0, -1);
}
function formatInputs(inputs, color) {
if (inputs instanceof Uint8Array) {
return inputs.length > 0 ? bytesToHexString(inputs) : undefined;
}
else {
const formattedName = color !== undefined ? color(inputs.name) : inputs.name;
return `${formattedName}(${inputs.arguments.join(", ")})`;
}
}
function formatOutputs(outputs) {
if (outputs instanceof Uint8Array) {
return outputs.length > 0 ? bytesToHexString(outputs) : undefined;
}
else {
return outputs;
}
}
function formatLog(log, colorizer) {
const { parameters } = log;
const tag = colorizer.yellow("[event]");
const lines = [];
if (Array.isArray(parameters)) {
const hexValues = parameters.map((bytes) => bytesToHexString(bytes));
const topicCount = hexValues.length - 1;
for (let i = 0; i < topicCount; i++) {
const prefix = i === 0 ? `${tag} topic 0` : ` topic ${i}`;
lines.push(`${prefix}: ${colorizer.cyan(hexValues[i])}`);
}
if (hexValues.length > 0) {
const dataPrefix = topicCount > 0 ? " data" : `${tag} data`;
lines.push(`${dataPrefix}: ${colorizer.cyan(hexValues[hexValues.length - 1])}`);
}
}
else {
lines.push(`${tag} ${parameters.name}(${colorizer.cyan(parameters.arguments.join(", "))})`);
}
return lines;
}
function formatTrace(trace, colorizer) {
const { success, address, contract, inputs, gasUsed, value, kind, isCheatcode, outputs, } = trace;
let color;
if (isCheatcode) {
color = colorizer.blue;
}
else if (success) {
color = colorizer.green;
}
else {
color = colorizer.red;
}
const formattedInputs = formatInputs(inputs, color);
const formattedOutputs = formatOutputs(outputs);
let openingLine;
let closingLine;
if (kind === CallKind.Create) {
openingLine = `[${gasUsed}] ${colorizer.yellow("→ new")} ${contract ?? "<unknown>"}@${address}`;
// TODO: Uncomment this when the formattedInputs starts containing
// the address of where the contract was deployed instead of the code.
// if (formattedInputs !== undefined) {
// openingLine = `${openingLine}@${formattedInputs}`;
// }
}
else {
openingLine = `[${gasUsed}] ${color(contract ?? address)}`;
if (formattedInputs !== undefined) {
openingLine = `${openingLine}::${formattedInputs}`;
}
if (value !== 0n) {
openingLine = `${openingLine} {value: ${value}}`;
}
if (kind === CallKind.StaticCall) {
openingLine = `${openingLine} ${colorizer.yellow("[staticcall]")}`;
}
else if (kind === CallKind.DelegateCall) {
openingLine = `${openingLine} ${colorizer.yellow("[delegatecall]")}`;
}
else if (kind === CallKind.CallCode) {
openingLine = `${openingLine} ${colorizer.yellow("[callcode]")}`;
}
}
if (formattedOutputs !== undefined) {
if (formattedOutputs === "EvmError: Revert" ||
formattedOutputs.startsWith("revert:")) {
closingLine = `${color("←")} ${color("[Revert]")} ${formattedOutputs}`;
}
else {
closingLine = `${color("←")} ${formattedOutputs}`;
}
}
const lines = [];
lines.push(openingLine);
for (const child of trace.children) {
if (child.kind === LogKind.Log) {
lines.push(formatLog(child, colorizer));
}
else {
lines.push(formatTrace(child, colorizer));
}
}
if (closingLine !== undefined) {
lines.push([closingLine]);
}
return lines;
}
function formatNestedArray(data, prefix = "", isTopLevel = true) {
let output = "";
for (let i = 0; i < data.length; i++) {
const item = data[i];
if (Array.isArray(item) && typeof item[0] === "string") {
const [label, ...children] = item;
if (isTopLevel) {
// Blank line between top-level traces
if (i > 0) {
output += "\n";
}
output += `${prefix}${label}\n`;
output += formatNestedArray(children, prefix, false);
}
else {
const isLast = i === data.length - 1;
const connector = isLast ? " └─ " : " ├─ ";
const childPrefix = isLast ? " " : " │ ";
output += `${prefix}${connector}${label}\n`;
output += formatNestedArray(children, prefix + childPrefix, false);
}
}
else if (typeof item === "string") {
const isLast = i === data.length - 1;
const connector = isLast ? " └─ " : " ├─ ";
output += `${prefix}${connector}${item}\n`;
}
}
return output;
}
//# sourceMappingURL=trace-formatters.js.map