UNPKG

hardhat

Version:

Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.

136 lines (119 loc) 3.51 kB
import chalk from "chalk"; import debug from "debug"; import { Reporter } from "../../sentry/reporter"; import { TracingConfig } from "../provider/node-types"; import { createModelsAndDecodeBytecodes } from "./compiler-to-model"; import { ContractsIdentifier } from "./contracts-identifier"; import { isCreateTrace, isEvmStep, isPrecompileTrace, MessageTrace, } from "./message-trace"; import { Bytecode, ContractFunctionType } from "./model"; import { FALLBACK_FUNCTION_NAME, RECEIVE_FUNCTION_NAME, UNRECOGNIZED_CONTRACT_NAME, UNRECOGNIZED_FUNCTION_NAME, } from "./solidity-stack-trace"; const log = debug("hardhat:core:hardhat-network:node"); export class VmTraceDecoder { constructor(private readonly _contractsIdentifier: ContractsIdentifier) {} public getContractAndFunctionNamesForCall( code: Buffer, calldata?: Buffer ): { contractName: string; functionName?: string } { const isCreate = calldata === undefined; const bytecode = this._contractsIdentifier.getBytecodeForCall( code, isCreate ); const contractName = bytecode?.contract.name ?? UNRECOGNIZED_CONTRACT_NAME; if (isCreate) { return { contractName, }; } else { if (bytecode === undefined) { return { contractName, functionName: "", }; } else { const func = bytecode.contract.getFunctionFromSelector( calldata.slice(0, 4) ); const functionName: string = func === undefined ? UNRECOGNIZED_FUNCTION_NAME : func.type === ContractFunctionType.FALLBACK ? FALLBACK_FUNCTION_NAME : func.type === ContractFunctionType.RECEIVE ? RECEIVE_FUNCTION_NAME : func.name; return { contractName, functionName, }; } } } public tryToDecodeMessageTrace(messageTrace: MessageTrace): MessageTrace { if (isPrecompileTrace(messageTrace)) { return messageTrace; } return { ...messageTrace, bytecode: this._contractsIdentifier.getBytecodeForCall( messageTrace.code, isCreateTrace(messageTrace) ), steps: messageTrace.steps.map((s) => isEvmStep(s) ? s : this.tryToDecodeMessageTrace(s) ), }; } public addBytecode(bytecode: Bytecode) { this._contractsIdentifier.addBytecode(bytecode); } } export function initializeVmTraceDecoder( vmTraceDecoder: VmTraceDecoder, tracingConfig: TracingConfig ) { if (tracingConfig.buildInfos === undefined) { return; } try { for (const buildInfo of tracingConfig.buildInfos) { const bytecodes = createModelsAndDecodeBytecodes( buildInfo.solcVersion, buildInfo.input, buildInfo.output ); for (const bytecode of bytecodes) { if ( tracingConfig.ignoreContracts === true && bytecode.contract.name.startsWith("Ignored") ) { continue; } vmTraceDecoder.addBytecode(bytecode); } } } catch (error) { console.warn( chalk.yellow( "The Hardhat Network tracing engine could not be initialized. Run Hardhat with --verbose to learn more." ) ); log( "Hardhat Network tracing disabled: ContractsIdentifier failed to be initialized. Please report this to help us improve Hardhat.\n", error ); if (error instanceof Error) { Reporter.reportError(error); } } }