Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
AccountOverride,
} from "@nomicfoundation/edr";
import { privateToAddress } from "@ethereumjs/util";
import { ContractDecoder, precompileP256Verify } from "@nomicfoundation/edr";
import {
ContractDecoder,
IncludeTraces,
precompileP256Verify,
} from "@nomicfoundation/edr";
import picocolors from "picocolors";
import debug from "debug";
import { EventEmitter } from "events";
Expand Down Expand Up @@ -67,7 +71,6 @@
MempoolOrder,
} from "./node-types";
import {
edrRpcDebugTraceToHardhat,
edrTracingMessageResultToMinimalEVMResult,
edrTracingMessageToMinimalMessage,
edrTracingStepToMinimalInterpreterStep,
Expand Down Expand Up @@ -268,7 +271,9 @@
},
},
networkId: BigInt(config.networkId),
observability: {},
observability: {
includeCallTraces: IncludeTraces.All,
},
ownedAccounts,
// Turn off the Osaka EIP-7825 per transaction gas limit for HH2
// when being run from `solidity-coverage`.
Expand Down Expand Up @@ -314,7 +319,7 @@
const context = await getGlobalEdrContext();
const provider = await context.createProvider(
GENERIC_CHAIN_TYPE,
edrProviderConfig,

Check failure on line 322 in packages/hardhat-core/src/internal/hardhat-network/provider/provider.ts

View workflow job for this annotation

GitHub Actions / Lint

Argument of type '{ allowBlocksWithSameTimestamp: boolean; allowUnlimitedContractSize: boolean; bailOnCallFailure: boolean; bailOnTransactionFailure: boolean; blockGasLimit: bigint; chainId: bigint; ... 12 more ...; transactionGasCap: bigint | undefined; }' is not assignable to parameter of type 'ProviderConfig'.
edrLoggerConfig,
edrSubscriptionConfig,
contractDecoder
Expand All @@ -326,7 +331,7 @@

const wrapper = new EdrProviderWrapper(
provider,
edrProviderConfig,

Check failure on line 334 in packages/hardhat-core/src/internal/hardhat-network/provider/provider.ts

View workflow job for this annotation

GitHub Actions / Lint

Argument of type '{ allowBlocksWithSameTimestamp: boolean; allowUnlimitedContractSize: boolean; bailOnCallFailure: boolean; bailOnTransactionFailure: boolean; blockGasLimit: bigint; chainId: bigint; ... 12 more ...; transactionGasCap: bigint | undefined; }' is not assignable to parameter of type 'ProviderConfig'.
edrLoggerConfig,
minimalEthereumJsNode,
edrSubscriptionConfig,
Expand Down Expand Up @@ -392,11 +397,8 @@
this._node._vm.events.eventNames().length > 0;

if (needsTraces) {
const rawTraces = responseObject.traces;
for (const rawTrace of rawTraces) {
// For other consumers in JS we need to marshall the entire trace over FFI
const trace = rawTrace.trace;

const rawTraces = responseObject.traces();

Check failure on line 400 in packages/hardhat-core/src/internal/hardhat-network/provider/provider.ts

View workflow job for this annotation

GitHub Actions / Lint

This expression is not callable because it is a 'get' accessor. Did you mean to use it without '()'?
for (const trace of rawTraces) {
// beforeTx event
if (this._node._vm.events.listenerCount("beforeTx") > 0) {
this._node._vm.events.emit("beforeTx");
Expand All @@ -413,7 +415,7 @@
}
}
// afterMessage event
else if ("executionResult" in traceItem) {
else if ("execResult" in traceItem) {
if (this._node._vm.evm.events.listenerCount("afterMessage") > 0) {
this._node._vm.evm.events.emit(
"afterMessage",
Expand Down Expand Up @@ -442,20 +444,32 @@
if (isErrorResponse(response)) {
let error;

let stackTrace: SolidityStackTrace | null = null;
try {
stackTrace = responseObject.stackTrace();
} catch (e) {
log("Failed to get stack trace: %O", e);
}
const stackTrace = responseObject.stackTrace();

if (stackTrace !== null) {
error = encodeSolidityStackTrace(response.error.message, stackTrace);
if (stackTrace?.kind === "StackTrace") {
error = encodeSolidityStackTrace(
response.error.message,
stackTrace.entries
);
// Pass data and transaction hash from the original error
(error as any).data = response.error.data?.data ?? undefined;
(error as any).transactionHash =
response.error.data?.transactionHash ?? undefined;
} else {
if (stackTrace !== null) {
switch (stackTrace.kind) {
case "UnexpectedError":
log(
"Failed to get stack trace due to error: %O",
stackTrace.errorMessage
);
break;
case "HeuristicFailed":
log("Failed to get stack trace due to failing heuristics");
break;
}
}

if (response.error.code === InvalidArgumentsError.CODE) {
error = new InvalidArgumentsError(response.error.message);
} else {
Expand All @@ -479,11 +493,6 @@
// e.g. `HardhatNetwork/2.19.0/@nomicfoundation/edr/0.2.0-dev`
if (args.method === "web3_clientVersion") {
return clientVersion(response.result);
} else if (
args.method === "debug_traceTransaction" ||
args.method === "debug_traceCall"
) {
return edrRpcDebugTraceToHardhat(response.result);
} else {
return response.result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,113 +174,43 @@
}
}

export function edrRpcDebugTraceToHardhat(
rpcDebugTrace: DebugTraceResult
): RpcDebugTraceOutput {
const structLogs = rpcDebugTrace.structLogs.map((log) => {
const result: RpcStructLog = {
depth: Number(log.depth),
gas: Number(log.gas),
gasCost: Number(log.gasCost),
op: log.opName,
pc: Number(log.pc),
};

if (log.memory !== undefined) {
result.memory = log.memory;
}

if (log.stack !== undefined) {
// Remove 0x prefix which is required by EIP-3155, but not expected by Hardhat.
result.stack = log.stack?.map((item) => item.slice(2));
}

if (log.storage !== undefined) {
result.storage = Object.fromEntries(
Object.entries(log.storage).map(([key, value]) => {
return [key.slice(2), value.slice(2)];
})
);
}

if (log.error !== undefined) {
result.error = {
message: log.error,
};
}

return result;
});

// REVM trace adds initial STOP that Hardhat doesn't expect
if (structLogs.length > 0 && structLogs[0].op === "STOP") {
structLogs.shift();
}

let returnValue = rpcDebugTrace.output?.toString() ?? "";
if (returnValue === "0x") {
returnValue = "";
}

return {
failed: !rpcDebugTrace.pass,
gas: Number(rpcDebugTrace.gasUsed),
returnValue,
structLogs,
};
}

export function edrTracingStepToMinimalInterpreterStep(
step: TracingStep
): MinimalInterpreterStep {
const minimalInterpreterStep: MinimalInterpreterStep = {
pc: Number(step.pc),
pc: step.pc,

Check failure on line 181 in packages/hardhat-core/src/internal/hardhat-network/provider/utils/convertToEdr.ts

View workflow job for this annotation

GitHub Actions / Lint

Type 'bigint' is not assignable to type 'number'.
depth: step.depth,
opcode: {
name: step.opcode,
name: step.opcode.name,

Check failure on line 184 in packages/hardhat-core/src/internal/hardhat-network/provider/utils/convertToEdr.ts

View workflow job for this annotation

GitHub Actions / Lint

Property 'name' does not exist on type 'string'.
},
stack: step.stack,
memory: step.memory,
};

if (step.memory !== undefined) {
minimalInterpreterStep.memory = step.memory;
}

return minimalInterpreterStep;
}

export function edrTracingMessageResultToMinimalEVMResult(
tracingMessageResult: TracingMessageResult
): MinimalEVMResult {
const { result, contractAddress } = tracingMessageResult.executionResult;

// only SuccessResult has logs
const success = "logs" in result;
const execResult = tracingMessageResult.execResult;

Check failure on line 196 in packages/hardhat-core/src/internal/hardhat-network/provider/utils/convertToEdr.ts

View workflow job for this annotation

GitHub Actions / Lint

Property 'execResult' does not exist on type 'TracingMessageResult'.

const minimalEVMResult: MinimalEVMResult = {
execResult: {
executionGasUsed: result.gasUsed,
success,
success: execResult.success,
executionGasUsed: execResult.executionGasUsed,
contractAddress:
execResult.contractAddress !== undefined
? new Address(execResult.contractAddress)
: undefined,
reason: execResult.reason,
output:
execResult.output !== undefined
? Buffer.from(execResult.output)
: undefined,
},
};

// only success and exceptional halt have reason
if ("reason" in result) {
minimalEVMResult.execResult.reason = result.reason;
}
if ("output" in result) {
const { output } = result;
if (output instanceof Uint8Array) {
minimalEVMResult.execResult.output = Buffer.from(output);
} else {
minimalEVMResult.execResult.output = Buffer.from(output.returnValue);
}
}

if (contractAddress !== undefined) {
minimalEVMResult.execResult.contractAddress = new Address(contractAddress);
}

return minimalEVMResult;
}

Expand Down
4 changes: 2 additions & 2 deletions packages/hardhat-core/test/builtin-tasks/compile.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getLatestSupportedSolcVersion } from "@nomicfoundation/edr";
import { latestSupportedSolidityVersion } from "@nomicfoundation/edr";
import { assert, expect } from "chai";
import ci from "ci-info";
import * as fsExtra from "fs-extra";
Expand Down Expand Up @@ -57,7 +57,7 @@ describe("compile task", function () {
// Test to check that the last version of solc is being tested
const userConfigSolcVersion = this.env.userConfig.solidity;

const lastSolcVersion = getLatestSupportedSolcVersion();
const lastSolcVersion = latestSupportedSolidityVersion();

assert.equal(
userConfigSolcVersion,
Expand Down
4 changes: 2 additions & 2 deletions packages/hardhat-core/test/helpers/compilation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getLatestSupportedSolcVersion } from "@nomicfoundation/edr";
import { latestSupportedSolidityVersion } from "@nomicfoundation/edr";
import semver from "semver";

import {
Expand Down Expand Up @@ -161,7 +161,7 @@ async function downloadCompiler(solidityVersion: string): Promise<void> {
}

export const getNextUnsupportedVersion = () =>
semver.inc(getLatestSupportedSolcVersion(), "patch")!;
semver.inc(latestSupportedSolidityVersion(), "patch")!;

export const getNextNextUnsupportedVersion = () =>
semver.inc(getNextUnsupportedVersion(), "patch")!;
Loading