Skip to content

Commit

Permalink
try to support trace and tracecall
Browse files Browse the repository at this point in the history
but there are some edge cases
  • Loading branch information
zemse committed May 23, 2024
1 parent bf5e9d8 commit 5fb463c
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 115 deletions.
220 changes: 106 additions & 114 deletions src/tasks/trace.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
import { TypedTransaction } from "@nomicfoundation/ethereumjs-tx";
// import { MinimalEthereumJsVm } from "hardhat/internal/hardhat-network/provider/vm/minimal-vm";
import { assert } from "console";
import createDebug from "debug";
import { ethers } from "ethers";
import { task } from "hardhat/config";
// import { ForkBlockchain } from "hardhat/internal/hardhat-network/provider/fork/ForkBlockchain";
// import { HardhatNode } from "hardhat/internal/hardhat-network/provider/node";
// import { FakeSenderAccessListEIP2930Transaction } from "hardhat/internal/hardhat-network/provider/transactions/FakeSenderAccessListEIP2930Transaction";
// import { FakeSenderEIP1559Transaction } from "hardhat/internal/hardhat-network/provider/transactions/FakeSenderEIP1559Transaction";
// import { FakeSenderTransaction } from "hardhat/internal/hardhat-network/provider/transactions/FakeSenderTransaction";
// import { HttpNetworkUserConfig } from "hardhat/types";

import { print } from "../print";
import { TraceRecorder } from "../trace-recorder";
import {
addCliParams,
applyCliArgsToTracer,
applyStateOverrides,
} from "../utils";
import { getHardhatBaseProvider } from "../utils/hardhat";
import { addCliParams, applyCliArgsToTracer } from "../utils";
import { HttpNetworkUserConfig } from "hardhat/types";
import { addRecorder } from "../extend/hre";
const debug = createDebug("hardhat-tracer:tasks:trace");

// TODO
Expand Down Expand Up @@ -47,123 +34,128 @@ const debug = createDebug("hardhat-tracer:tasks:trace");
addCliParams(task("trace", "Traces a transaction hash"))
.addParam("hash", "transaction hash to view trace of")
.addOptionalParam("rpc", "archive node")
.setAction(async (args: any, hre: any, runSuper: any) => {
.setAction(async (args, hre, runSuper) => {
applyCliArgsToTracer(args, hre);

throw new Error(
"trace transaction is currently not supported for hardhat EDR"
);
// throw new Error(
// "trace transaction is currently not supported for hardhat EDR"
// );

// if (!args.nocompile) {
// await hre.run("compile");
// }

// debug("fetch tx from provider");
// const tx = await hre.network.provider.send("eth_getTransactionByHash", [
// args.hash,
// ]);
if (!args.nocompile) {
await hre.run("compile");
}

// // if tx is not on hardhat local, then use rpc
// if (tx == null) {
// debug("tx not on provider");
// // try using url specified in network as rpc url
// if (args.network) {
// const userNetworks = hre.userConfig.networks;
// if (userNetworks === undefined) {
// throw new Error(
// "[hardhat-tracer]: No networks found in hardhat config"
// );
// }
// if (userNetworks[args.network] === undefined) {
// throw new Error(
// `[hardhat-tracer]: Network ${args.network} not found in hardhat config`
// );
// }
// const url = (userNetworks[args.network] as HttpNetworkUserConfig).url;
// if (url === undefined) {
// throw new Error(
// `[hardhat-tracer]: Url not found in hardhat-config->networks->${args.network}`
// );
// }
// if (args.rpc === undefined) {
// args.rpc = url;
// }
// }
debug("fetch tx from provider");
const tx = await hre.network.provider.send("eth_getTransactionByHash", [
args.hash,
]);

// // try using current mainnet fork url as rpc url
// const mainnetForkUrl = (hre.network.config as any).forking?.url;
// if (mainnetForkUrl && args.rpc === undefined) {
// args.rpc = mainnetForkUrl;
// }
// if tx is not on hardhat local, then use rpc
if (tx == null) {
debug("tx not on provider");
// try using url specified in network as rpc url
if (args.network) {
const userNetworks = hre.userConfig.networks;
if (userNetworks === undefined) {
throw new Error(
"[hardhat-tracer]: No networks found in hardhat config"
);
}
if (userNetworks[args.network] === undefined) {
throw new Error(
`[hardhat-tracer]: Network ${args.network} not found in hardhat config`
);
}
const url = (userNetworks[args.network] as HttpNetworkUserConfig).url;
if (url === undefined) {
throw new Error(
`[hardhat-tracer]: Url not found in hardhat-config->networks->${args.network}`
);
}
if (args.rpc === undefined) {
args.rpc = url;
}
}

// if (!args.rpc) {
// // TODO add auto-detect network
// throw new Error(
// "[hardhat-tracer]: rpc url not provided, please either use --network <network-name> or --rpc <rpc-url>"
// );
// }
// debug("fetch tx from rpc %s", args.rpc);
// const provider = new ethers.providers.StaticJsonRpcProvider(args.rpc);
// const txFromRpc = await provider.getTransaction(args.hash);
// try using current mainnet fork url as rpc url
const mainnetForkUrl = (hre.network.config as any).forking?.url;
if (mainnetForkUrl && args.rpc === undefined) {
args.rpc = mainnetForkUrl;
}

// if (txFromRpc == null) {
// throw new Error(
// "[hardhat-tracer]: Transaction not found on rpc. Are you sure the transaction is confirmed on this network?"
// );
// }
if (!args.rpc) {
// TODO add auto-detect network
throw new Error(
"[hardhat-tracer]: rpc url not provided, please either use --network <network-name> or --rpc <rpc-url>"
);
}
debug("fetch tx from rpc %s", args.rpc);
const provider = new ethers.providers.StaticJsonRpcProvider(args.rpc);
const txFromRpc = await provider.getTransaction(args.hash);

// if (!txFromRpc.blockNumber) {
// throw new Error(
// "[hardhat-tracer]: Transaction is not mined yet, please wait for it to be mined"
// );
// }
if (txFromRpc == null) {
throw new Error(
"[hardhat-tracer]: Transaction not found on rpc. Are you sure the transaction is confirmed on this network?"
);
}

// // TODO add support for decoding using debug_tt on the RPC if present, otherwise use hardhat mainnet fork
// if (false) {
// // decode response of debug_traceTransaction
// // print
// return; // should halt execution here
// }
if (!txFromRpc.blockNumber) {
throw new Error(
"[hardhat-tracer]: Transaction is not mined yet, please wait for it to be mined"
);
}

// console.warn("Activating mainnet fork at block", txFromRpc.blockNumber);
// await hre.network.provider.send("hardhat_reset", [
// {
// forking: {
// jsonRpcUrl: args.rpc,
// blockNumber: txFromRpc.blockNumber,
// },
// },
// ]);
// TODO add support for decoding using debug_tt on the RPC if present, otherwise use hardhat mainnet fork
if (false) {
// decode response of debug_traceTransaction
// print
return; // should halt execution here
}

// // after the above hardhat reset, tx should be present on the local node
// }
console.warn("Activating mainnet fork at block", txFromRpc.blockNumber);
await hre.network.provider.send("hardhat_reset", [
{
forking: {
jsonRpcUrl: args.rpc,
blockNumber: txFromRpc.blockNumber,
},
},
]);
addRecorder(hre); // reset seems to clear all what we did to the provider
// after the above hardhat reset, tx should be present on the local node
}

// debug("get VM");
debug("get VM");
// const node = await getNode(hre);

// // we cant use this resp because stack and memory is not there (takes up lot of memory if enabled)
// // await node.traceTransaction(Buffer.from(args.hash.slice(2), "hex"), {
// // disableStorage: true,
// // disableMemory: true,
// // disableStack: true,
// // });
// we cant use this resp because stack and memory is not there (takes up lot of memory if enabled)
// await node.traceTransaction(Buffer.from(args.hash.slice(2), "hex"), {
// disableStorage: true,
// disableMemory: true,
// disableStack: true,
// });

// debug("trace transaction");
debug("trace transaction");
// const txFinal = await hre.ethers.provider.getTransaction(args.hash);
// if (!txFinal) {
// throw new Error("Transaction is still null, this should not happen");
// }
console.log(args.hash);
await hre.network.provider.send("debug_traceTransaction", [args.hash]);
// await traceTransctionWithProgress(node, args.hash);

// // TODO try to do this properly
// // @ts-ignore
// const recorder = (global?._hardhat_tracer_recorder as unknown) as TraceRecorder;
// TODO try to do this properly
const recorder = hre.tracer.recorder!;

// debug("printing trace");
// await print(recorder.previousTraces[recorder.previousTraces.length - 1], {
// artifacts: hre.artifacts,
// tracerEnv: hre.tracer,
// provider: hre.ethers.provider,
// });
debug("printing trace");
await print(recorder.previousTraces[recorder.previousTraces.length - 1], {
artifacts: hre.artifacts,
tracerEnv: hre.tracer,
provider: hre.ethers.provider,
});

// await new Promise((resolve) => setTimeout(resolve, 1000));
// return;
await new Promise((resolve) => setTimeout(resolve, 1000));
return;
});

// async function traceTransctionWithProgress(node: HardhatNode, hash: string) {
Expand Down
2 changes: 1 addition & 1 deletion test/project.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe("Hardhat Runtime Environment extension", function () {
});
});

describe.skip("Trace task", function () {
describe("Trace task", function () {
useEnvironment("hardhat-project");

before(async function () {
Expand Down

0 comments on commit 5fb463c

Please sign in to comment.