From b99dd9a502c1f24e522901cc730671e52b3b7b2a Mon Sep 17 00:00:00 2001 From: galargh Date: Thu, 24 Oct 2024 16:28:08 +0100 Subject: [PATCH] chore: do not expose edr types via user config --- .../builtin-plugins/solidity-test/helpers.ts | 101 ++++++++++++++++- .../solidity-test/task-action.ts | 19 ++-- .../builtin-plugins/solidity/config.ts | 106 ++++++++++-------- .../solidity/type-extensions.ts | 63 ++++++++++- 4 files changed, 230 insertions(+), 59 deletions(-) diff --git a/v-next/hardhat/src/internal/builtin-plugins/solidity-test/helpers.ts b/v-next/hardhat/src/internal/builtin-plugins/solidity-test/helpers.ts index a5f71e45ce..d8c725ad7d 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/solidity-test/helpers.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/solidity-test/helpers.ts @@ -1,10 +1,109 @@ +import type { RunOptions } from "./runner.js"; import type { ArtifactsManager } from "../../../types/artifacts.js"; -import type { Artifact } from "@ignored/edr"; +import type { SolidityTestUserConfig } from "../../../types/config.js"; +import type { + Artifact, + SolidityTestRunnerConfigArgs, + CachedChains, + CachedEndpoints, + PathPermission, + StorageCachingConfig, + AddressLabel, +} from "@ignored/edr"; import { HardhatError } from "@ignored/hardhat-vnext-errors"; import { exists } from "@ignored/hardhat-vnext-utils/fs"; +import { hexStringToBytes } from "@ignored/hardhat-vnext-utils/hex"; import { resolveFromRoot } from "@ignored/hardhat-vnext-utils/path"; +function hexStringToBuffer(hexString: string): Buffer { + return Buffer.from(hexStringToBytes(hexString)); +} + +export function solidityTestUserConfigToRunOptions( + config: SolidityTestUserConfig, +): RunOptions { + return config; +} + +export function solidityTestUserConfigToSolidityTestRunnerConfigArgs( + projectRoot: string, + config: SolidityTestUserConfig, +): SolidityTestRunnerConfigArgs { + const fsPermissions: PathPermission[] | undefined = [ + config.fsPermissions?.readWrite?.map((path) => ({ access: 0, path })) ?? [], + config.fsPermissions?.read?.map((path) => ({ access: 0, path })) ?? [], + config.fsPermissions?.write?.map((path) => ({ access: 0, path })) ?? [], + ].flat(1); + + const labels: AddressLabel[] | undefined = config.labels?.map( + ({ address, label }) => ({ + address: hexStringToBuffer(address), + label, + }), + ); + + let rpcStorageCaching: StorageCachingConfig | undefined; + if (config.rpcStorageCaching !== undefined) { + let chains: CachedChains | string[]; + if (Array.isArray(config.rpcStorageCaching.chains)) { + chains = config.rpcStorageCaching.chains; + } else { + const rpcStorageCachingChains: "All" | "None" = + config.rpcStorageCaching.chains; + switch (rpcStorageCachingChains) { + case "All": + chains = 0; + break; + case "None": + chains = 1; + break; + } + } + let endpoints: CachedEndpoints | string; + if (config.rpcStorageCaching.endpoints instanceof RegExp) { + endpoints = config.rpcStorageCaching.endpoints.source; + } else { + const rpcStorageCachingEndpoints: "All" | "Remote" = + config.rpcStorageCaching.endpoints; + switch (rpcStorageCachingEndpoints) { + case "All": + endpoints = 0; + break; + case "Remote": + endpoints = 1; + break; + } + } + rpcStorageCaching = { + chains, + endpoints, + }; + } + + const sender: Buffer | undefined = + config.sender === undefined ? undefined : hexStringToBuffer(config.sender); + const txOrigin: Buffer | undefined = + config.txOrigin === undefined + ? undefined + : hexStringToBuffer(config.txOrigin); + const blockCoinbase: Buffer | undefined = + config.blockCoinbase === undefined + ? undefined + : hexStringToBuffer(config.blockCoinbase); + + return { + projectRoot, + ...config, + fsPermissions, + labels, + sender, + txOrigin, + blockCoinbase, + rpcStorageCaching, + }; +} + export async function getArtifacts( hardhatArtifacts: ArtifactsManager, ): Promise { diff --git a/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts b/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts index de109dd96b..151545d798 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts @@ -5,7 +5,12 @@ import type { SolidityTestRunnerConfigArgs } from "@ignored/edr"; import { finished } from "node:stream/promises"; -import { getArtifacts, isTestArtifact } from "./helpers.js"; +import { + getArtifacts, + isTestArtifact, + solidityTestUserConfigToRunOptions, + solidityTestUserConfigToSolidityTestRunnerConfigArgs, +} from "./helpers.js"; import { testReporter } from "./reporter.js"; import { run } from "./runner.js"; @@ -32,12 +37,12 @@ const runSolidityTests: NewTaskActionFunction = async (_taskArguments, hre) => { const profile = hre.config.solidity.profiles[profileName]; const testOptions = profile.test; - const config: SolidityTestRunnerConfigArgs = { - projectRoot: hre.config.paths.root, - ...testOptions, - }; - - const options: RunOptions = testOptions; + const config: SolidityTestRunnerConfigArgs = + solidityTestUserConfigToSolidityTestRunnerConfigArgs( + hre.config.paths.root, + testOptions, + ); + const options: RunOptions = solidityTestUserConfigToRunOptions(testOptions); const runStream = run(artifacts, testSuiteIds, config, options); diff --git a/v-next/hardhat/src/internal/builtin-plugins/solidity/config.ts b/v-next/hardhat/src/internal/builtin-plugins/solidity/config.ts index e1040a30ce..d3f802e946 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/solidity/config.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/solidity/config.ts @@ -36,67 +36,83 @@ const solcUserConfigType = z.object({ }); const solidityTestUserConfigType = z.object({ - // RunOptions timeout: z.number().optional(), - // Omit - fsPermissions: z.array(z.object({ - access: z.enum(["ReadWrite", "Read", "Write"]), - path: z.string(), - })).optional(), + fsPermissions: z + .object({ + readWrite: z.array(z.string()).optional(), + read: z.array(z.string()).optional(), + write: z.array(z.string()).optional(), + }) + .optional(), trace: z.boolean().optional(), testFail: z.boolean().optional(), - labels: z.array(z.object({ - address: z.instanceof(Buffer), - label: z.string(), - })).optional(), + labels: z + .array( + z.object({ + address: z.string().startsWith("0x"), + label: z.string(), + }), + ) + .optional(), isolate: z.boolean().optional(), ffi: z.boolean().optional(), - sender: z.instanceof(Buffer).optional(), - txOrigin: z.instanceof(Buffer).optional(), + sender: z.string().startsWith("0x").optional(), + txOrigin: z.string().startsWith("0x").optional(), initialBalance: z.bigint().optional(), blockBaseFeePerGas: z.bigint().optional(), - blockCoinbase: z.instanceof(Buffer).optional(), + blockCoinbase: z.string().startsWith("0x").optional(), blockTimestamp: z.bigint().optional(), blockDifficulty: z.bigint().optional(), blockGasLimit: z.bigint().optional(), disableBlockGasLimit: z.boolean().optional(), memoryLimit: z.bigint().optional(), ethRpcUrl: z.string().optional(), - forkBlockNumber: z.number().optional(), + forkBlockNumber: z.bigint().optional(), rpcEndpoints: z.record(z.string()).optional(), rpcCachePath: z.string().optional(), - rpcStorageCaching: z.object({ - chains: unionType([ - z.array(z.string()), - z.enum(["All", "None"]), - ], ""), - endpoints: unionType([ - z.string(), - z.enum(["All", "Remote"]), - ], ""), - }).optional(), + rpcStorageCaching: z + .object({ + chains: unionType( + [z.enum(["All", "None"]), z.array(z.string())], + "Expected `All`, `None` or a list of chain names to cache", + ), + endpoints: unionType( + [ + z.enum(["All", "Remote"]), + z.object({ + source: z.string(), + }), + ], + "Expected `All`, `Remote` or a RegExp object matching endpoints to cacche", + ), + }) + .optional(), promptTimeout: z.number().optional(), - fuzz: z.object({ - failurePersistDir: z.string().optional(), - failurePersistFile: z.string().optional(), - runs: z.number().optional(), - maxTestRejects: z.number().optional(), - seed: z.string().optional(), - dictionaryWeight: z.number().optional(), - includeStorage: z.boolean().optional(), - includePushBytes: z.boolean().optional(), - }).optional(), - invariant: z.object({ - failurePersistDir: z.string().optional(), - runs: z.number().optional(), - depth: z.number().optional(), - failOnRevert: z.boolean().optional(), - callOverride: z.boolean().optional(), - dictionaryWeight: z.number().optional(), - includeStorage: z.boolean().optional(), - includePushBytes: z.boolean().optional(), - shrinkRunLimit: z.number().optional(), - }).optional(), + fuzz: z + .object({ + failurePersistDir: z.string().optional(), + failurePersistFile: z.string().optional(), + runs: z.number().optional(), + maxTestRejects: z.number().optional(), + seed: z.string().optional(), + dictionaryWeight: z.number().optional(), + includeStorage: z.boolean().optional(), + includePushBytes: z.boolean().optional(), + }) + .optional(), + invariant: z + .object({ + failurePersistDir: z.string().optional(), + runs: z.number().optional(), + depth: z.number().optional(), + failOnRevert: z.boolean().optional(), + callOverride: z.boolean().optional(), + dictionaryWeight: z.number().optional(), + includeStorage: z.boolean().optional(), + includePushBytes: z.boolean().optional(), + shrinkRunLimit: z.number().optional(), + }) + .optional(), }); const singleVersionSolcUserConfigType = solcUserConfigType.extend({ diff --git a/v-next/hardhat/src/internal/builtin-plugins/solidity/type-extensions.ts b/v-next/hardhat/src/internal/builtin-plugins/solidity/type-extensions.ts index 84b7f07e7f..209dc93978 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/solidity/type-extensions.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/solidity/type-extensions.ts @@ -13,8 +13,62 @@ declare module "../../../types/config.js" { settings?: any; } - export type SolidityTestUserConfig = RunOptions & - Omit; + export interface SolidityTestUserConfig { + timeout?: number; + fsPermissions?: { + readWrite?: string[]; + read?: string[]; + write?: string[]; + }; + trace?: boolean; + testFail?: boolean; + labels?: Array<{ + address: string; // 0x-prefixed hex string + label: string; + }>; + isolate?: boolean; + ffi?: boolean; + sender?: string; // 0x-prefixed hex string + txOrigin?: string; // 0x-prefixed hex string + initialBalance?: bigint; + blockBaseFeePerGas?: bigint; + blockCoinbase?: string; // 0x-prefixed hex string + blockTimestamp?: bigint; + blockDifficulty?: bigint; + blockGasLimit?: bigint; + disableBlockGasLimit?: boolean; + memoryLimit?: bigint; + ethRpcUrl?: string; + forkBlockNumber?: bigint; + rpcEndpoints?: Record; + rpcCachePath?: string; + rpcStorageCaching?: { + chains: "All" | "None" | string[]; + endpoints: "All" | "Remote" | RegExp; + }; + promptTimeout?: number; + fuzz?: { + failurePersistDir?: string; + failurePersistFile?: string; + runs?: number; + maxTestRejects?: number; + seed?: string; + dictionaryWeight?: number; + includeStorage?: boolean; + includePushBytes?: boolean; + }; + invariant?: { + failurePersistDir?: string; + runs?: number; + depth?: number; + failOnRevert?: boolean; + callOverride?: boolean; + dictionaryWeight?: number; + includeStorage?: boolean; + includePushBytes?: boolean; + shrinkRunLimit?: number; + }; + } export interface SingleVersionSolcUserConfig extends SolcUserConfig { test?: SolidityTestUserConfig; @@ -56,8 +110,7 @@ declare module "../../../types/config.js" { settings: any; } - export type SolidityTestConfig = RunOptions & - Omit; + export type SolidityTestConfig = SolidityTestUserConfig; export interface SolidityBuildProfileConfig { compilers: SolcConfig[]; @@ -86,8 +139,6 @@ declare module "../../../types/config.js" { import "../../../types/hre.js"; import type { SolidityBuildSystem } from "../../../types/solidity/build-system.js"; -import type { RunOptions } from "../solidity-test/types.js"; -import type { SolidityTestRunnerConfigArgs } from "@ignored/edr"; declare module "../../../types/hre.js" { export interface HardhatRuntimeEnvironment {