Skip to content

Commit

Permalink
Add tracer_lastTrace method to JSON-RPC
Browse files Browse the repository at this point in the history
  • Loading branch information
piwonskp committed Feb 8, 2024
1 parent 80d7197 commit ffb2f71
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 35 deletions.
48 changes: 27 additions & 21 deletions src/extend/hre.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand All @@ -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;
}
}
35 changes: 33 additions & 2 deletions src/tasks/node.ts
Original file line number Diff line number Diff line change
@@ -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<unknown> {
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[]);
}
}
18 changes: 12 additions & 6 deletions src/utils/task-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 9 additions & 6 deletions src/wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit ffb2f71

Please sign in to comment.