hardhat-tracer
Version:
Hardhat Tracer plugin
119 lines (104 loc) • 3.8 kB
text/typescript
import createDebug from "debug";
import { ethers } from "ethers";
import { task } from "hardhat/config";
import { HttpNetworkUserConfig } from "hardhat/types";
import { print } from "../print";
import { addCliParams, applyCliArgsToTracer, colorError } from "../utils";
import { addRecorder } from "../extend/hre";
const debug = createDebug("hardhat-tracer:tasks:trace");
addCliParams(task("tracecall", "Traces a call"))
.addParam("to", "destination address")
.addOptionalParam("data", "input call data")
.addOptionalParam("value", "value to send")
.addOptionalParam("gaslimit", "gas limit")
.addOptionalParam("gasprice", "gas price")
.addOptionalParam("blocknumber", "block number")
.addOptionalParam("from", "from address")
.addOptionalParam("rpc", "archive node")
.setAction(async (args, hre, runSuper) => {
applyCliArgsToTracer(args, hre);
if (!args.nocompile) {
await hre.run("compile");
}
// 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;
}
// 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}`
);
}
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("using rpc url %s", args.rpc);
const provider = new ethers.providers.StaticJsonRpcProvider(args.rpc);
if (args.blocknumber === undefined) {
args.blocknumber = await provider.getBlockNumber();
}
console.warn(
"Activating mainnet fork at block",
args.rpc,
args.blocknumber
);
await hre.network.provider.send("hardhat_reset", [
{
forking: {
jsonRpcUrl: args.rpc,
blockNumber: Number(args.blocknumber),
},
},
]);
addRecorder(hre); // reset seems to clear all what we did to the provider
await hre.tracer.switch!.enable();
try {
debug("making call");
const result = await hre.ethers.provider.call({
to: args.to,
data: args.data,
value: args.value,
gasLimit: args.gaslimit,
gasPrice: args.gasprice,
from: args.from,
});
console.log("eth_call result:", result);
} catch (e) {
console.error("eth_call error:", (e as any).error);
}
// TODO try to do this properly
const recorder = hre.tracer.recorder!;
debug("printing trace");
if (!recorder.previousTraces || recorder.previousTraces.length === 0) {
throw new Error("[hardhat-tracer]: Failed to record the 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;
// const txFromRpc = await provider.getTransaction(args.hash);
// after the above hardhat reset, tx should be present on the local node
});