diff --git a/src/extend/hre.ts b/src/extend/hre.ts index 1fa5291..a7f59b2 100644 --- a/src/extend/hre.ts +++ b/src/extend/hre.ts @@ -7,6 +7,7 @@ import { Decoder } from "../decoder"; import { TraceRecorder } from "../trace-recorder"; import { TracerEnv } from "../types"; import { applyStateOverrides, getVM } from "../utils"; +import { HardhatRuntimeEnvironment } from "hardhat/types/runtime"; const debug = createDebug("hardhat-tracer:extend:hre"); declare module "hardhat/types/runtime" { @@ -31,27 +32,32 @@ extendEnvironment((hre) => { // @ts-ignore global.hreArtifacts = hre.artifacts; - // wait for VM to be initialized - getVM(hre) - .then(async (vm) => { - hre.tracer.recorder = new TraceRecorder(vm, hre.tracer); - if (hre.tracer.stateOverrides) { - try { - await applyStateOverrides( - hre.tracer.stateOverrides, - vm, - hre.artifacts - ); - } catch {} - } - }) - .catch((e) => { - debug( - "Could not get VM, hardhat tracer is disabled. Error: " + e.message - ); - // if for some reason we can't get the vm, disable hardhat-tracer - hre.tracer.enabled = false; - }); + addRecorder(hre); debug("environment extended!"); }); + + +export async function addRecorder(hre: HardhatRuntimeEnvironment) { + // wait for VM to be initialized + try { + const vm = await getVM(hre); + + hre.tracer.recorder = new TraceRecorder(vm, hre.tracer); + if (hre.tracer.stateOverrides) { + try { + await applyStateOverrides( + hre.tracer.stateOverrides, + vm, + hre.artifacts + ); + } catch {} + } + } catch (e: any) { + debug( + "Could not get VM, hardhat tracer is disabled. Error: " + e.message + ); + // if for some reason we can't get the vm, disable hardhat-tracer + hre.tracer.enabled = false; + } +} \ No newline at end of file diff --git a/src/tasks/node.ts b/src/tasks/node.ts index 4b2bc08..6ff250a 100644 --- a/src/tasks/node.ts +++ b/src/tasks/node.ts @@ -1,3 +1,34 @@ -import { registerTask } from "../utils"; +import { EIP1193Provider, HardhatRuntimeEnvironment, RequestArguments } from "hardhat/types"; +import { ProviderLike } from "../types"; +import { runTask, createTracerTask } from "../utils"; +import { ProviderWrapper } from "hardhat/internal/core/providers/wrapper"; +import { wrapProvider } from "../wrapper"; +import { subtask } from "hardhat/config"; +import { TASK_NODE_GET_PROVIDER } from "hardhat/builtin-tasks/task-names"; +import { addRecorder } from "../extend/hre"; -registerTask("node"); + +createTracerTask("node").setAction(runTask); + +subtask(TASK_NODE_GET_PROVIDER).setAction( + async (args, hre, runSuper) => { + const provider = await runSuper(args); + wrapProvider(hre, new RpcWrapper(hre, provider)); + addRecorder(hre); + return hre.network.provider + } +) + +class RpcWrapper extends ProviderWrapper { + constructor(public hre: HardhatRuntimeEnvironment, public provider: ProviderLike) { + super((provider as unknown) as EIP1193Provider); + } + + public async request({method, params}: RequestArguments): Promise { + if(method === "tracer_lastTrace") { + let trace = this.hre.tracer.lastTrace(); + return JSON.parse(JSON.stringify(trace, (k, v) => (k === "parent") ? undefined : v)); + } + return await this.provider.send(method, params as any[]); + } +} diff --git a/src/utils/task-helpers.ts b/src/utils/task-helpers.ts index 1274212..f51a93a 100644 --- a/src/utils/task-helpers.ts +++ b/src/utils/task-helpers.ts @@ -9,17 +9,23 @@ import { wrapHardhatProvider } from "../wrapper"; import { checkIfOpcodesAreValid } from "./check-opcodes"; export function registerTask(taskName: string) { - return addCliParams(task(taskName, `Run hardhat: ${taskName}`)).setAction( - async (args, hre, runSuper) => { - applyCliArgsToTracer(args, hre); - + return createTracerTask(taskName).setAction( + (args: any, hre: HardhatRuntimeEnvironment, runSuper: any) => { wrapHardhatProvider(hre); - - return runSuper(args); + return runTask(args, hre, runSuper); } ); } +export function createTracerTask(taskName: string) { + return addCliParams(task(taskName, `Run hardhat: ${taskName}`)); +} + +export async function runTask(args: any, hre: HardhatRuntimeEnvironment, runSuper: any) { + applyCliArgsToTracer(args, hre); + return runSuper(args); +} + export function addCliParams(_task: ConfigurableTaskDefinition) { return ( _task diff --git a/src/wrapper.ts b/src/wrapper.ts index a42e45a..63e7879 100644 --- a/src/wrapper.ts +++ b/src/wrapper.ts @@ -104,18 +104,21 @@ class TracerWrapper extends ProviderWrapper { * @param hre: HardhatRuntimeEnvironment - required to get access to contract artifacts and tracer env */ export function wrapHardhatProvider(hre: HardhatRuntimeEnvironment) { + wrapProvider(hre, new TracerWrapper({ + artifacts: hre.artifacts, + tracerEnv: hre.tracer, + provider: hre.network.provider, + })); +} + +export function wrapProvider(hre: HardhatRuntimeEnvironment, wrapper: ProviderWrapper) { // do not wrap if already wrapped if (isTracerAlreadyWrappedInHreProvider(hre)) { return; } - const tracerProvider = new TracerWrapper({ - artifacts: hre.artifacts, - tracerEnv: hre.tracer, - provider: hre.network.provider, - }); const compatibleProvider = new BackwardsCompatibilityProviderAdapter( - tracerProvider + wrapper ); hre.network.provider = compatibleProvider; }