hardhat-tracer
Advanced tools
Comparing version 2.0.0-beta.3 to 2.0.0-beta.4
import { ErrorFragment, EventFragment, Fragment, FunctionFragment, Result } from "ethers/lib/utils"; | ||
import { Artifacts } from "hardhat/types"; | ||
import { TracerCache } from "./cache"; | ||
declare type Mapping<FragmentType> = Map<string, Array<{ | ||
@@ -8,2 +9,3 @@ contractName: string; | ||
export declare class Decoder { | ||
cache: TracerCache; | ||
functionFragmentsBySelector: Mapping<FunctionFragment>; | ||
@@ -13,3 +15,3 @@ errorFragmentsBySelector: Mapping<ErrorFragment>; | ||
ready: Promise<void>; | ||
constructor(artifacts: Artifacts); | ||
constructor(artifacts: Artifacts, cache: TracerCache); | ||
updateArtifacts(artifacts: Artifacts): Promise<void>; | ||
@@ -16,0 +18,0 @@ _updateArtifacts(artifacts: Artifacts): Promise<void>; |
@@ -7,6 +7,7 @@ "use strict"; | ||
class Decoder { | ||
constructor(artifacts) { | ||
constructor(artifacts, cache) { | ||
this.functionFragmentsBySelector = new Map(); | ||
this.errorFragmentsBySelector = new Map(); | ||
this.eventFragmentsByTopic0 = new Map(); | ||
this.cache = cache; | ||
this.ready = this._updateArtifacts(artifacts); | ||
@@ -37,14 +38,14 @@ } | ||
try { | ||
return decode(inputData, returnData, "function", this.functionFragmentsBySelector); | ||
return decode(inputData, returnData, "function", this.functionFragmentsBySelector, this.cache); | ||
} | ||
catch { } | ||
return decode(inputData, returnData, "error", this.errorFragmentsBySelector); | ||
return decode(inputData, returnData, "error", this.errorFragmentsBySelector, this.cache); | ||
} | ||
async decodeFunction(inputData, returnData) { | ||
await this.ready; | ||
return decode(inputData, returnData, "function", this.functionFragmentsBySelector); | ||
return decode(inputData, returnData, "function", this.functionFragmentsBySelector, this.cache); | ||
} | ||
async decodeError(revertData) { | ||
await this.ready; | ||
const { fragment, inputResult, contractName } = await decode(revertData, "0x", "error", this.errorFragmentsBySelector); | ||
const { fragment, inputResult, contractName } = await decode(revertData, "0x", "error", this.errorFragmentsBySelector, this.cache); | ||
return { fragment, revertResult: inputResult, contractName }; | ||
@@ -89,3 +90,3 @@ } | ||
} | ||
async function decode(inputData, returnData, type, mapping) { | ||
async function decode(inputData, returnData, type, mapping, cache) { | ||
const selector = inputData.slice(0, 10); | ||
@@ -120,3 +121,3 @@ // console.log("selector", selector); | ||
try { | ||
const { fragment, inputResult } = await decodeUsing4byteDirectory(selector, inputData, mapping); | ||
const { fragment, inputResult } = await decodeUsing4byteDirectory(selector, inputData, mapping, cache); | ||
return { fragment, inputResult }; | ||
@@ -129,6 +130,16 @@ } | ||
} | ||
async function decodeUsing4byteDirectory(selector, inputData, mapping) { | ||
const response = await (0, utils_1.fetchJson)("https://www.4byte.directory/api/v1/signatures/?hex_signature=" + selector); | ||
async function decodeUsing4byteDirectory(selector, inputData, mapping, cache) { | ||
let responseResults; | ||
const cacheVal = cache.fourByteDir.get(selector); | ||
if (cacheVal) { | ||
responseResults = cacheVal; | ||
} | ||
else { | ||
const response = await (0, utils_1.fetchJson)("https://www.4byte.directory/api/v1/signatures/?hex_signature=" + selector); | ||
responseResults = response.results; | ||
cache.fourByteDir.set(selector, responseResults); | ||
cache.save(); | ||
} | ||
// console.log("response", response); | ||
for (const result of response.results) { | ||
for (const result of responseResults) { | ||
// console.log({ result }); | ||
@@ -135,0 +146,0 @@ try { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const config_1 = require("hardhat/config"); | ||
const cache_1 = require("../cache"); | ||
const utils_1 = require("../utils"); | ||
@@ -19,2 +20,5 @@ (0, config_1.extendConfig)((config, userConfig) => { | ||
} | ||
const cache = new cache_1.TracerCache(); | ||
cache.setCachePath(config.paths.cache); | ||
cache.load(); | ||
config.tracer = { | ||
@@ -32,3 +36,3 @@ enabled: userConfig.tracer?.enabled ?? false, | ||
printNameTagTip: undefined, | ||
tokenDecimalsCache: new Map(), | ||
cache, | ||
}, | ||
@@ -35,0 +39,0 @@ stateOverrides: userConfig.tracer?.stateOverrides, |
@@ -13,3 +13,3 @@ "use strict"; | ||
hre.tracer = hre.config.tracer; | ||
hre.tracer.decoder = new decoder_1.Decoder(hre.artifacts); | ||
hre.tracer.decoder = new decoder_1.Decoder(hre.artifacts, hre.tracer._internal.cache); | ||
// @ts-ignore | ||
@@ -16,0 +16,0 @@ global.tracerEnv = hre.tracer; |
@@ -42,4 +42,4 @@ "use strict"; | ||
// see if we already know the decimals | ||
const { tokenDecimalsCache } = dependencies.tracerEnv._internal; | ||
const decimals = tokenDecimalsCache.get(to); | ||
const { cache } = dependencies.tracerEnv._internal; | ||
const decimals = cache.tokenDecimals.get(to); | ||
if (decimals) { | ||
@@ -54,7 +54,8 @@ // if we know decimals then use it | ||
if (contractDecimals !== undefined) { | ||
tokenDecimalsCache.set(to, contractDecimals); | ||
cache.tokenDecimals.set(to, contractDecimals); | ||
} | ||
else { | ||
tokenDecimalsCache.set(to, -1); | ||
cache.tokenDecimals.set(to, -1); | ||
} | ||
cache.save(); | ||
} | ||
@@ -61,0 +62,0 @@ } |
@@ -5,2 +5,3 @@ import { Artifacts } from "hardhat/types"; | ||
import { BigNumberish } from "ethers"; | ||
import { TracerCache } from "./cache"; | ||
export interface NameTags { | ||
@@ -28,3 +29,3 @@ [address: string]: string; | ||
_internal: { | ||
tokenDecimalsCache: Map<string, number>; | ||
cache: TracerCache; | ||
printNameTagTip: undefined | "print it" | "already printed"; | ||
@@ -31,0 +32,0 @@ }; |
@@ -29,3 +29,3 @@ import { BigNumber } from "ethers"; | ||
export declare function applyStateOverrides(stateOverrides: StateOverrides, vm: VM, artifacts: Artifacts): Promise<void>; | ||
export declare function fetchContractName(to: string, provider: ProviderLike): Promise<string | undefined>; | ||
export declare function fetchContractName(to: string, dependencies: TracerDependencies): Promise<string | undefined>; | ||
export declare function fetchContractNameFromMethodName(to: string, methodName: string, provider: ProviderLike): Promise<string | undefined>; | ||
@@ -32,0 +32,0 @@ export declare function fetchContractDecimals(to: string, provider: ProviderLike): Promise<number | undefined>; |
@@ -233,10 +233,22 @@ "use strict"; | ||
exports.applyStateOverrides = applyStateOverrides; | ||
async function fetchContractName(to, provider) { | ||
let name = await fetchContractNameFromMethodName(to, "symbol", provider); | ||
async function fetchContractName(to, dependencies) { | ||
const { cache } = dependencies.tracerEnv._internal; | ||
const cacheResult = cache.contractNames.get(to); | ||
if (cacheResult) { | ||
if (cacheResult === "unknown") { | ||
return undefined; | ||
} | ||
return cacheResult; | ||
} | ||
let name = await fetchContractNameFromMethodName(to, "symbol", dependencies.provider); | ||
if (!name) { | ||
name = await fetchContractNameFromMethodName(to, "name", provider); | ||
name = await fetchContractNameFromMethodName(to, "name", dependencies.provider); | ||
} | ||
if (name) { | ||
// format the name a bit | ||
name = name.split(" ").join(""); | ||
} | ||
// set the cache, so we don't do the request again | ||
cache.contractNames.set(to, name ?? "unknown"); | ||
cache.save(); | ||
return name; | ||
@@ -316,3 +328,3 @@ } | ||
dependencies.tracerEnv.enabled = false; // disable tracer to avoid tracing these calls | ||
const contractNameFromNameMethod = await fetchContractName(address, dependencies.provider); | ||
const contractNameFromNameMethod = await fetchContractName(address, dependencies); | ||
dependencies.tracerEnv.enabled = true; // enable tracer back | ||
@@ -319,0 +331,0 @@ if (contractNameFromNameMethod) { |
@@ -7,2 +7,3 @@ "use strict"; | ||
const wrapper_1 = require("hardhat/internal/core/providers/wrapper"); | ||
const cache_1 = require("./cache"); | ||
const decoder_1 = require("./decoder"); | ||
@@ -100,2 +101,4 @@ const utils_1 = require("./utils"); | ||
// const tracerEnv = getTracerEnvFromUserInput(tracerEnvUser); | ||
const cache = new cache_1.TracerCache(); | ||
const decoder = new decoder_1.Decoder(artifacts, cache); | ||
if (!tracerEnv) { | ||
@@ -114,5 +117,6 @@ tracerEnv = { | ||
printNameTagTip: undefined, | ||
tokenDecimalsCache: new Map(), | ||
// tokenDecimalsCache: new Map(), | ||
cache, | ||
}, | ||
decoder: new decoder_1.Decoder(artifacts), | ||
decoder, | ||
}; | ||
@@ -119,0 +123,0 @@ } |
{ | ||
"name": "hardhat-tracer", | ||
"version": "2.0.0-beta.3", | ||
"version": "2.0.0-beta.4", | ||
"description": "Hardhat Tracer plugin", | ||
@@ -5,0 +5,0 @@ "repository": "github:zemse/hardhat-tracer", |
@@ -12,2 +12,3 @@ import { ethers } from "ethers"; | ||
import { Artifacts } from "hardhat/types"; | ||
import { TracerCache } from "./cache"; | ||
@@ -20,2 +21,4 @@ type Mapping<FragmentType> = Map< | ||
export class Decoder { | ||
cache: TracerCache; | ||
functionFragmentsBySelector: Mapping<FunctionFragment> = new Map(); | ||
@@ -27,3 +30,4 @@ errorFragmentsBySelector: Mapping<ErrorFragment> = new Map(); | ||
constructor(artifacts: Artifacts) { | ||
constructor(artifacts: Artifacts, cache: TracerCache) { | ||
this.cache = cache; | ||
this.ready = this._updateArtifacts(artifacts); | ||
@@ -73,3 +77,4 @@ } | ||
"function", | ||
this.functionFragmentsBySelector | ||
this.functionFragmentsBySelector, | ||
this.cache | ||
); | ||
@@ -82,3 +87,4 @@ } catch {} | ||
"error", | ||
this.errorFragmentsBySelector | ||
this.errorFragmentsBySelector, | ||
this.cache | ||
); | ||
@@ -102,3 +108,4 @@ } | ||
"function", | ||
this.functionFragmentsBySelector | ||
this.functionFragmentsBySelector, | ||
this.cache | ||
); | ||
@@ -120,3 +127,4 @@ } | ||
"error", | ||
this.errorFragmentsBySelector | ||
this.errorFragmentsBySelector, | ||
this.cache | ||
); | ||
@@ -185,3 +193,4 @@ return { fragment, revertResult: inputResult, contractName }; | ||
type: "function", | ||
mapping: Mapping<FunctionFragment> | ||
mapping: Mapping<FunctionFragment>, | ||
cache: TracerCache | ||
): Promise<{ | ||
@@ -198,3 +207,4 @@ fragment: Fragment; | ||
type: "error", | ||
mapping: Mapping<ErrorFragment> | ||
mapping: Mapping<ErrorFragment>, | ||
cache: TracerCache | ||
): Promise<{ | ||
@@ -211,3 +221,4 @@ fragment: Fragment; | ||
type: string, | ||
mapping: Mapping<Fragment> | ||
mapping: Mapping<Fragment>, | ||
cache: TracerCache | ||
) { | ||
@@ -256,3 +267,4 @@ const selector = inputData.slice(0, 10); | ||
inputData, | ||
mapping | ||
mapping, | ||
cache | ||
); | ||
@@ -270,3 +282,4 @@ return { fragment, inputResult }; | ||
inputData: string, | ||
mapping: Mapping<Fragment> | ||
mapping: Mapping<Fragment>, | ||
cache: TracerCache | ||
): Promise<{ | ||
@@ -276,8 +289,17 @@ fragment: Fragment; | ||
}> { | ||
const response = await fetchJson( | ||
"https://www.4byte.directory/api/v1/signatures/?hex_signature=" + selector | ||
); | ||
let responseResults; | ||
const cacheVal = cache.fourByteDir.get(selector); | ||
if (cacheVal) { | ||
responseResults = cacheVal; | ||
} else { | ||
const response = await fetchJson( | ||
"https://www.4byte.directory/api/v1/signatures/?hex_signature=" + selector | ||
); | ||
responseResults = response.results; | ||
cache.fourByteDir.set(selector, responseResults); | ||
cache.save(); | ||
} | ||
// console.log("response", response); | ||
for (const result of response.results) { | ||
for (const result of responseResults) { | ||
// console.log({ result }); | ||
@@ -284,0 +306,0 @@ |
@@ -1,8 +0,5 @@ | ||
import { | ||
extendConfig, | ||
extendEnvironment, | ||
experimentalAddHardhatNetworkMessageTraceHook, | ||
} from "hardhat/config"; | ||
import { MessageTrace } from "hardhat/internal/hardhat-network/stack-traces/message-trace"; | ||
import { extendConfig } from "hardhat/config"; | ||
import { HardhatConfig, HardhatUserConfig } from "hardhat/types"; | ||
import { TracerCache } from "../cache"; | ||
@@ -42,2 +39,6 @@ import { TracerEnv, TracerEnvUser } from "../types"; | ||
const cache = new TracerCache(); | ||
cache.setCachePath(config.paths.cache); | ||
cache.load(); | ||
config.tracer = { | ||
@@ -55,3 +56,3 @@ enabled: userConfig.tracer?.enabled ?? false, | ||
printNameTagTip: undefined, | ||
tokenDecimalsCache: new Map(), | ||
cache, | ||
}, | ||
@@ -58,0 +59,0 @@ stateOverrides: userConfig.tracer?.stateOverrides, |
@@ -20,3 +20,3 @@ import { extendEnvironment } from "hardhat/config"; | ||
hre.tracer = hre.config.tracer; | ||
hre.tracer.decoder = new Decoder(hre.artifacts); | ||
hre.tracer.decoder = new Decoder(hre.artifacts, hre.tracer._internal.cache); | ||
@@ -23,0 +23,0 @@ // @ts-ignore |
@@ -57,4 +57,4 @@ import { BigNumber, BigNumberish } from "ethers"; | ||
// see if we already know the decimals | ||
const { tokenDecimalsCache } = dependencies.tracerEnv._internal; | ||
const decimals = tokenDecimalsCache.get(to); | ||
const { cache } = dependencies.tracerEnv._internal; | ||
const decimals = cache.tokenDecimals.get(to); | ||
if (decimals) { | ||
@@ -68,6 +68,7 @@ // if we know decimals then use it | ||
if (contractDecimals !== undefined) { | ||
tokenDecimalsCache.set(to, contractDecimals); | ||
cache.tokenDecimals.set(to, contractDecimals); | ||
} else { | ||
tokenDecimalsCache.set(to, -1); | ||
cache.tokenDecimals.set(to, -1); | ||
} | ||
cache.save(); | ||
} | ||
@@ -74,0 +75,0 @@ } |
@@ -1,6 +0,6 @@ | ||
import { VM } from "@nomicfoundation/ethereumjs-vm"; | ||
import { Artifacts, EthereumProvider } from "hardhat/types"; | ||
import { Artifacts } from "hardhat/types"; | ||
import { TraceRecorder } from "./trace/recorder"; | ||
import { Decoder } from "./decoder"; | ||
import { BigNumberish } from "ethers"; | ||
import { TracerCache } from "./cache"; | ||
@@ -32,3 +32,3 @@ export interface NameTags { | ||
_internal: { | ||
tokenDecimalsCache: Map<string, number>; | ||
cache: TracerCache; | ||
printNameTagTip: | ||
@@ -35,0 +35,0 @@ | undefined // meaning "no need to print" |
@@ -331,10 +331,35 @@ import { | ||
export async function fetchContractName(to: string, provider: ProviderLike) { | ||
let name = await fetchContractNameFromMethodName(to, "symbol", provider); | ||
export async function fetchContractName( | ||
to: string, | ||
dependencies: TracerDependencies | ||
) { | ||
const { cache } = dependencies.tracerEnv._internal; | ||
const cacheResult = cache.contractNames.get(to); | ||
if (cacheResult) { | ||
if (cacheResult === "unknown") { | ||
return undefined; | ||
} | ||
return cacheResult; | ||
} | ||
let name = await fetchContractNameFromMethodName( | ||
to, | ||
"symbol", | ||
dependencies.provider | ||
); | ||
if (!name) { | ||
name = await fetchContractNameFromMethodName(to, "name", provider); | ||
name = await fetchContractNameFromMethodName( | ||
to, | ||
"name", | ||
dependencies.provider | ||
); | ||
} | ||
if (name) { | ||
// format the name a bit | ||
name = name.split(" ").join(""); | ||
} | ||
// set the cache, so we don't do the request again | ||
cache.contractNames.set(to, name ?? "unknown"); | ||
cache.save(); | ||
return name; | ||
@@ -430,3 +455,3 @@ } | ||
address, | ||
dependencies.provider | ||
dependencies | ||
); | ||
@@ -433,0 +458,0 @@ dependencies.tracerEnv.enabled = true; // enable tracer back |
@@ -10,2 +10,3 @@ import { ethers } from "ethers"; | ||
} from "hardhat/types"; | ||
import { TracerCache } from "./cache"; | ||
import { Decoder } from "./decoder"; | ||
@@ -129,2 +130,4 @@ | ||
// const tracerEnv = getTracerEnvFromUserInput(tracerEnvUser); | ||
const cache = new TracerCache(); | ||
const decoder = new Decoder(artifacts, cache); | ||
if (!tracerEnv) { | ||
@@ -143,5 +146,6 @@ tracerEnv = { | ||
printNameTagTip: undefined, | ||
tokenDecimalsCache: new Map(), | ||
// tokenDecimalsCache: new Map(), | ||
cache, | ||
}, | ||
decoder: new Decoder(artifacts), | ||
decoder, | ||
}; | ||
@@ -148,0 +152,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
353078
241
6282
2