UNPKG

hardhat

Version:

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

189 lines (167 loc) 5.42 kB
import type { RunOptions } from "./runner.js"; import type { Abi } from "../../../types/artifacts.js"; import type { ChainType } from "../../../types/network.js"; import type { SolidityTestConfig } from "../../../types/test.js"; import type { SolidityTestRunnerConfigArgs, PathPermission, Artifact, ObservabilityConfig, } from "@nomicfoundation/edr"; import { opGenesisState, opLatestHardfork, l1GenesisState, l1HardforkLatest, IncludeTraces, FsAccessPermission, CollectStackTraces, } from "@nomicfoundation/edr"; import { hexStringToBytes } from "@nomicfoundation/hardhat-utils/hex"; import chalk from "chalk"; import { DEFAULT_VERBOSITY, OPTIMISM_CHAIN_TYPE } from "../../constants.js"; import { type Colorizer, formatArtifactId } from "./formatters.js"; interface SolidityTestConfigParams { chainType: ChainType; projectRoot: string; config: SolidityTestConfig; verbosity: number; observability?: ObservabilityConfig; testPattern?: string; generateGasReport: boolean; } function hexStringToBuffer(hexString: string): Buffer { return Buffer.from(hexStringToBytes(hexString)); } export function solidityTestConfigToRunOptions( config: SolidityTestConfig, ): RunOptions { return config; } export async function solidityTestConfigToSolidityTestRunnerConfigArgs({ chainType, projectRoot, config, verbosity, observability, testPattern, generateGasReport, }: SolidityTestConfigParams): Promise<SolidityTestRunnerConfigArgs> { const fsPermissions: PathPermission[] | undefined = [ config.fsPermissions?.readWriteFile?.map((p) => ({ access: FsAccessPermission.ReadWriteFile, path: p, })) ?? [], config.fsPermissions?.readFile?.map((p) => ({ access: FsAccessPermission.ReadFile, path: p, })) ?? [], config.fsPermissions?.writeFile?.map((p) => ({ access: FsAccessPermission.WriteFile, path: p, })) ?? [], config.fsPermissions?.dangerouslyReadWriteDirectory?.map((p) => ({ access: FsAccessPermission.DangerouslyReadWriteDirectory, path: p, })) ?? [], config.fsPermissions?.readDirectory?.map((p) => ({ access: FsAccessPermission.ReadDirectory, path: p, })) ?? [], config.fsPermissions?.dangerouslyWriteDirectory?.map((p) => ({ access: FsAccessPermission.DangerouslyWriteDirectory, path: p, })) ?? [], ].flat(1); const sender: Buffer | undefined = config.from === undefined ? undefined : hexStringToBuffer(config.from); const txOrigin: Buffer | undefined = config.txOrigin === undefined ? undefined : hexStringToBuffer(config.txOrigin); const blockCoinbase: Buffer | undefined = config.coinbase === undefined ? undefined : hexStringToBuffer(config.coinbase); const localPredeploys = chainType === OPTIMISM_CHAIN_TYPE ? opGenesisState(opLatestHardfork()) : l1GenesisState(l1HardforkLatest()); let includeTraces: IncludeTraces = IncludeTraces.None; if (verbosity >= 5) { includeTraces = IncludeTraces.All; } else if (verbosity >= 3) { includeTraces = IncludeTraces.Failing; } const blockGasLimit = config.blockGasLimit === false ? undefined : config.blockGasLimit; const disableBlockGasLimit = config.blockGasLimit === false; const blockDifficulty = config.prevRandao; let ethRpcUrl: string | undefined; if (config.forking?.url !== undefined) { ethRpcUrl = await config.forking.url.get(); } const forkBlockNumber = config.forking?.blockNumber; let rpcEndpoints: Record<string, string> | undefined; if (config.forking?.rpcEndpoints !== undefined) { rpcEndpoints = {}; for (const [name, configValue] of Object.entries( config.forking.rpcEndpoints, )) { rpcEndpoints[name] = await configValue.get(); } } const shouldAlwaysCollectStackTraces = verbosity > DEFAULT_VERBOSITY; return { projectRoot, ...config, fsPermissions, localPredeploys, sender, txOrigin, blockCoinbase, observability, testPattern, includeTraces, blockGasLimit, disableBlockGasLimit, blockDifficulty, ethRpcUrl, forkBlockNumber, rpcEndpoints, generateGasReport, collectStackTraces: shouldAlwaysCollectStackTraces ? CollectStackTraces.Always : CollectStackTraces.OnFailure, }; } export function isTestSuiteArtifact(artifact: Artifact): boolean { const abi: Abi = JSON.parse(artifact.contract.abi); return abi.some(({ type, name }) => { if (type === "function" && typeof name === "string") { return name.startsWith("test") || name.startsWith("invariant"); } return false; }); } export function warnDeprecatedTestFail( artifact: Artifact, sourceNameToUserSourceName: Map<string, string>, colorizer: Colorizer = chalk, ): void { const abi: Abi = JSON.parse(artifact.contract.abi); abi.forEach(({ type, name }) => { if ( type === "function" && typeof name === "string" && name.startsWith("testFail") ) { const formattedLocation = formatArtifactId( artifact.id, sourceNameToUserSourceName, ); const warningMessage = `${colorizer.yellow("Warning")}: ${name} The support for the prefix \`testFail*\` has been removed. Consider using \`vm.expectRevert()\` for testing reverts in ${formattedLocation}\n`; console.warn(warningMessage); } }); }