Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/funny-socks-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hardhat": patch
---

Added support for EDR structured Solidity test cheatcode errors.
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ import type {
InternalFunctionCallStackEntry,
ContractCallRunOutOfGasError,
CheatcodeErrorStackTraceEntry,
CheatcodeErrorDetails,
} from "@nomicfoundation/edr";

import {
StackTraceEntryType,
CheatcodeErrorCode,
stackTraceEntryTypeToString,
FALLBACK_FUNCTION_NAME,
RECEIVE_FUNCTION_NAME,
Expand All @@ -42,6 +44,7 @@ import {
export {
SourceReference,
StackTraceEntryType,
CheatcodeErrorCode,
stackTraceEntryTypeToString,
FALLBACK_FUNCTION_NAME,
RECEIVE_FUNCTION_NAME,
Expand Down Expand Up @@ -77,6 +80,7 @@ export type {
ContractTooLargeErrorStackTraceEntry,
InternalFunctionCallStackEntry,
ContractCallRunOutOfGasError,
CheatcodeErrorDetails,
};

export type SolidityStackTraceEntry =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { panicErrorCodeToMessage } from "@nomicfoundation/hardhat-utils/panic-er

import {
StackTraceEntryType,
CheatcodeErrorCode,
CONSTRUCTOR_FUNCTION_NAME,
PRECOMPILE_FUNCTION_NAME,
UNKNOWN_FUNCTION_NAME,
Expand Down Expand Up @@ -266,9 +267,25 @@ function getMessageFromLastStackTraceEntry(
return `VM Exception while processing transaction: ${panicMessage}`;

case StackTraceEntryType.CUSTOM_ERROR:
case StackTraceEntryType.CHEATCODE_ERROR:
return `VM Exception while processing transaction: ${stackTraceEntry.message}`;

case StackTraceEntryType.CHEATCODE_ERROR: {
let message = stackTraceEntry.message;

if (stackTraceEntry.details !== undefined) {
switch (stackTraceEntry.details.code) {
case CheatcodeErrorCode.UnsupportedCheatcode:
message = `Cheatcode '${stackTraceEntry.details.cheatcode}' is not supported by Hardhat.`;
break;
case CheatcodeErrorCode.MissingCheatcode:
message = `Cheatcode '${stackTraceEntry.details.cheatcode}' is not yet available in this version of Hardhat.`;
break;
}
}

return `VM Exception while processing transaction: ${message}`;
}
Comment thread
ChristopherDedominici marked this conversation as resolved.

case StackTraceEntryType.OTHER_EXECUTION_ERROR:
// TODO: What if there was returnData?
return `Transaction reverted and Hardhat couldn't infer the reason.`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import type { SolidityStackTraceEntry } from "../network-manager/edr/stack-trace

import { panicErrorCodeToMessage } from "@nomicfoundation/hardhat-utils/panic-errors";

import { StackTraceEntryType } from "../network-manager/edr/stack-traces/solidity-stack-trace.js";
import {
StackTraceEntryType,
CheatcodeErrorCode,
} from "../network-manager/edr/stack-traces/solidity-stack-trace.js";

export function getMessageFromLastStackTraceEntry(
stackTraceEntry: SolidityStackTraceEntry,
Expand Down Expand Up @@ -64,8 +67,18 @@ export function getMessageFromLastStackTraceEntry(
case StackTraceEntryType.CUSTOM_ERROR:
return stackTraceEntry.message;

case StackTraceEntryType.CHEATCODE_ERROR:
case StackTraceEntryType.CHEATCODE_ERROR: {
if (stackTraceEntry.details !== undefined) {
switch (stackTraceEntry.details.code) {
case CheatcodeErrorCode.UnsupportedCheatcode:
return `Cheatcode '${stackTraceEntry.details.cheatcode}' is not supported by Hardhat.`;
case CheatcodeErrorCode.MissingCheatcode:
return `Cheatcode '${stackTraceEntry.details.cheatcode}' is not yet available in this version of Hardhat.`;
}
}

return stackTraceEntry.message;
}

case StackTraceEntryType.CONTRACT_TOO_LARGE_ERROR:
return "Trying to deploy a contract whose code is too large";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type {
SolidityStackTraceEntry,
StackTraceEntryType,
} from "../../../../../../src/internal/builtin-plugins/network-manager/edr/stack-traces/solidity-stack-trace.js";
import type { SolidityStackTraceEntry } from "../../../../../../src/internal/builtin-plugins/network-manager/edr/stack-traces/solidity-stack-trace.js";

import assert from "node:assert/strict";
import { describe, it } from "node:test";

import { CheatcodeErrorCode, StackTraceEntryType } from "@nomicfoundation/edr";

import { SolidityCallSite } from "../../../../../../src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-solidity-errors.js";
import { getMessageFromLastStackTraceEntry } from "../../../../../../src/internal/builtin-plugins/solidity-test/stack-trace-solidity-errors.js";

Comment thread
ChristopherDedominici marked this conversation as resolved.
describe("SolidityCallSite", function () {
describe("toString", function () {
Expand Down Expand Up @@ -58,3 +58,61 @@ describe("SolidityCallSite", function () {
});
});
});

describe("getMessageFromLastStackTraceEntry", () => {
const dummySourceReference = {
sourceName: "Test.t.sol",
sourceContent: "",
line: 1,
range: [0, 0],
};

describe("CHEATCODE_ERROR", () => {
it("returns the raw message when details is undefined", () => {
const entry: SolidityStackTraceEntry = {
type: StackTraceEntryType.CHEATCODE_ERROR,
message: "cheatcode 'broadcast(address)' is not supported",
sourceReference: dummySourceReference,
};

assert.equal(
getMessageFromLastStackTraceEntry(entry),
"cheatcode 'broadcast(address)' is not supported",
);
});

it("returns a Hardhat-specific message for unsupported cheatcodes", () => {
const entry: SolidityStackTraceEntry = {
type: StackTraceEntryType.CHEATCODE_ERROR,
message: "cheatcode 'broadcast(address)' is not supported",
sourceReference: dummySourceReference,
details: {
code: CheatcodeErrorCode.UnsupportedCheatcode,
cheatcode: "broadcast(address)",
},
};

assert.equal(
getMessageFromLastStackTraceEntry(entry),
"Cheatcode 'broadcast(address)' is not supported by Hardhat.",
);
});

it("returns a Hardhat-specific message for missing cheatcodes", () => {
const entry: SolidityStackTraceEntry = {
type: StackTraceEntryType.CHEATCODE_ERROR,
message: "unknown cheatcode with selector '0x12345678'",
sourceReference: dummySourceReference,
details: {
code: CheatcodeErrorCode.MissingCheatcode,
cheatcode: "someNewCheatcode(uint256)",
},
};

assert.equal(
getMessageFromLastStackTraceEntry(entry),
"Cheatcode 'someNewCheatcode(uint256)' is not yet available in this version of Hardhat.",
);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import type { SolidityStackTraceEntry } from "../../../../src/internal/builtin-plugins/network-manager/edr/stack-traces/solidity-stack-trace.js";

import assert from "node:assert/strict";
import { describe, it } from "node:test";

import {
CheatcodeErrorCode,
StackTraceEntryType,
} from "@nomicfoundation/edr";

import { getMessageFromLastStackTraceEntry } from "../../../../src/internal/builtin-plugins/solidity-test/stack-trace-solidity-errors.js";

describe("getMessageFromLastStackTraceEntry", () => {
const dummySourceReference = {
sourceName: "Test.t.sol",
sourceContent: "",
line: 1,
range: [0, 0],
};

describe("CHEATCODE_ERROR", () => {
it("returns the raw message when details is undefined", () => {
const entry: SolidityStackTraceEntry = {
type: StackTraceEntryType.CHEATCODE_ERROR,
message: "cheatcode 'broadcast(address)' is not supported",
sourceReference: dummySourceReference,
};

assert.equal(
getMessageFromLastStackTraceEntry(entry),
"cheatcode 'broadcast(address)' is not supported",
);
});

it("returns a Hardhat-specific message for unsupported cheatcodes", () => {
const entry: SolidityStackTraceEntry = {
type: StackTraceEntryType.CHEATCODE_ERROR,
message: "cheatcode 'broadcast(address)' is not supported",
sourceReference: dummySourceReference,
details: {
code: CheatcodeErrorCode.UnsupportedCheatcode,
cheatcode: "broadcast(address)",
},
};

assert.equal(
getMessageFromLastStackTraceEntry(entry),
"Cheatcode 'broadcast(address)' is not supported by Hardhat.",
);
});

it("returns a Hardhat-specific message for missing cheatcodes", () => {
const entry: SolidityStackTraceEntry = {
type: StackTraceEntryType.CHEATCODE_ERROR,
message: "unknown cheatcode with selector '0x12345678'",
sourceReference: dummySourceReference,
details: {
code: CheatcodeErrorCode.MissingCheatcode,
cheatcode: "someNewCheatcode(uint256)",
},
};

assert.equal(
getMessageFromLastStackTraceEntry(entry),
"Cheatcode 'someNewCheatcode(uint256)' is not yet available in this version of Hardhat.",
);
});
});
});
Loading