hardhat 3.1.8 → 3.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/src/config.d.ts +20 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +31 -0
- package/dist/src/config.js.map +1 -1
- package/dist/src/internal/builtin-plugins/coverage/coverage-manager.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/coverage/coverage-manager.js +33 -21
- package/dist/src/internal/builtin-plugins/coverage/coverage-manager.js.map +1 -1
- package/dist/src/internal/builtin-plugins/coverage/hook-handlers/solidity.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/coverage/hook-handlers/solidity.js +7 -8
- package/dist/src/internal/builtin-plugins/coverage/hook-handlers/solidity.js.map +1 -1
- package/dist/src/internal/builtin-plugins/coverage/instrumentation.d.ts +27 -0
- package/dist/src/internal/builtin-plugins/coverage/instrumentation.d.ts.map +1 -0
- package/dist/src/internal/builtin-plugins/coverage/instrumentation.js +27 -0
- package/dist/src/internal/builtin-plugins/coverage/instrumentation.js.map +1 -0
- package/dist/src/internal/builtin-plugins/flatten/task-action.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/flatten/task-action.js +1 -1
- package/dist/src/internal/builtin-plugins/flatten/task-action.js.map +1 -1
- package/dist/src/internal/builtin-plugins/gas-analytics/gas-analytics-manager.d.ts +0 -1
- package/dist/src/internal/builtin-plugins/gas-analytics/gas-analytics-manager.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/gas-analytics/gas-analytics-manager.js +4 -8
- package/dist/src/internal/builtin-plugins/gas-analytics/gas-analytics-manager.js.map +1 -1
- package/dist/src/internal/builtin-plugins/network-manager/hook-handlers/config.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/network-manager/hook-handlers/config.js +58 -20
- package/dist/src/internal/builtin-plugins/network-manager/hook-handlers/config.js.map +1 -1
- package/dist/src/internal/builtin-plugins/network-manager/type-validation.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/network-manager/type-validation.js +8 -0
- package/dist/src/internal/builtin-plugins/network-manager/type-validation.js.map +1 -1
- package/dist/src/internal/builtin-plugins/node/task-action.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/node/task-action.js +1 -2
- package/dist/src/internal/builtin-plugins/node/task-action.js.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.js +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.js.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/compiler/downloader.d.ts +0 -3
- package/dist/src/internal/builtin-plugins/solidity/build-system/compiler/downloader.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/compiler/downloader.js +8 -10
- package/dist/src/internal/builtin-plugins/solidity/build-system/compiler/downloader.js.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/dependency-graph-building.d.ts +2 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/dependency-graph-building.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/dependency-graph-building.js +4 -2
- package/dist/src/internal/builtin-plugins/solidity/build-system/dependency-graph-building.js.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.d.ts +3 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.js +8 -2
- package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.js.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/error-messages.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/error-messages.js +19 -5
- package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/error-messages.js.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.d.ts +8 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.js +54 -20
- package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.js.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity/type-extensions.d.ts +22 -0
- package/dist/src/internal/builtin-plugins/solidity/type-extensions.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity-test/config.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity-test/config.js +1 -0
- package/dist/src/internal/builtin-plugins/solidity-test/config.js.map +1 -1
- package/dist/src/internal/builtin-plugins/solidity-test/type-extensions.d.ts +1 -0
- package/dist/src/internal/builtin-plugins/solidity-test/type-extensions.d.ts.map +1 -1
- package/dist/src/internal/cli/error-handler.d.ts.map +1 -1
- package/dist/src/internal/cli/error-handler.js +15 -0
- package/dist/src/internal/cli/error-handler.js.map +1 -1
- package/dist/src/internal/cli/telemetry/sentry/reporter.d.ts.map +1 -1
- package/dist/src/internal/cli/telemetry/sentry/reporter.js +4 -0
- package/dist/src/internal/cli/telemetry/sentry/reporter.js.map +1 -1
- package/dist/src/internal/cli/telemetry/sentry/transport.js +1 -0
- package/dist/src/internal/cli/telemetry/sentry/transport.js.map +1 -1
- package/dist/src/internal/core/config-validation.d.ts +3 -3
- package/dist/src/internal/core/config-validation.d.ts.map +1 -1
- package/dist/src/internal/core/config-validation.js +48 -18
- package/dist/src/internal/core/config-validation.js.map +1 -1
- package/dist/src/internal/core/tasks/builders.d.ts +26 -16
- package/dist/src/internal/core/tasks/builders.d.ts.map +1 -1
- package/dist/src/internal/core/tasks/builders.js +65 -6
- package/dist/src/internal/core/tasks/builders.js.map +1 -1
- package/dist/src/internal/core/tasks/resolved-task.d.ts +2 -2
- package/dist/src/internal/core/tasks/resolved-task.d.ts.map +1 -1
- package/dist/src/internal/core/tasks/resolved-task.js +23 -9
- package/dist/src/internal/core/tasks/resolved-task.js.map +1 -1
- package/dist/src/internal/core/tasks/task-manager.d.ts.map +1 -1
- package/dist/src/internal/core/tasks/task-manager.js +14 -6
- package/dist/src/internal/core/tasks/task-manager.js.map +1 -1
- package/dist/src/internal/core/tasks/validations.d.ts +2 -0
- package/dist/src/internal/core/tasks/validations.d.ts.map +1 -1
- package/dist/src/internal/core/tasks/validations.js +11 -0
- package/dist/src/internal/core/tasks/validations.js.map +1 -1
- package/dist/src/internal/deprecated-module-imported-from-hardhat2-plugin.d.ts +2 -0
- package/dist/src/internal/deprecated-module-imported-from-hardhat2-plugin.d.ts.map +1 -0
- package/dist/src/internal/deprecated-module-imported-from-hardhat2-plugin.js +12 -0
- package/dist/src/internal/deprecated-module-imported-from-hardhat2-plugin.js.map +1 -0
- package/dist/src/internal/using-hardhat2-plugin-errors.d.ts +35 -0
- package/dist/src/internal/using-hardhat2-plugin-errors.d.ts.map +1 -0
- package/dist/src/internal/using-hardhat2-plugin-errors.js +98 -0
- package/dist/src/internal/using-hardhat2-plugin-errors.js.map +1 -0
- package/dist/src/plugins.d.ts +8 -0
- package/dist/src/plugins.d.ts.map +1 -1
- package/dist/src/plugins.js +13 -0
- package/dist/src/plugins.js.map +1 -1
- package/dist/src/types/index.d.ts +15 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +15 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/types/plugins.d.ts +2 -2
- package/dist/src/types/solidity/errors.d.ts +18 -0
- package/dist/src/types/solidity/errors.d.ts.map +1 -1
- package/dist/src/types/solidity/errors.js.map +1 -1
- package/dist/src/types/tasks.d.ts +95 -34
- package/dist/src/types/tasks.d.ts.map +1 -1
- package/package.json +10 -6
- package/src/config.ts +37 -0
- package/src/internal/builtin-plugins/coverage/coverage-manager.ts +57 -50
- package/src/internal/builtin-plugins/coverage/hook-handlers/solidity.ts +6 -17
- package/src/internal/builtin-plugins/coverage/instrumentation.ts +52 -0
- package/src/internal/builtin-plugins/flatten/task-action.ts +1 -0
- package/src/internal/builtin-plugins/gas-analytics/gas-analytics-manager.ts +6 -11
- package/src/internal/builtin-plugins/network-manager/hook-handlers/config.ts +65 -21
- package/src/internal/builtin-plugins/network-manager/type-validation.ts +9 -0
- package/src/internal/builtin-plugins/node/task-action.ts +2 -2
- package/src/internal/builtin-plugins/solidity/build-system/build-system.ts +1 -0
- package/src/internal/builtin-plugins/solidity/build-system/compiler/downloader.ts +14 -11
- package/src/internal/builtin-plugins/solidity/build-system/dependency-graph-building.ts +23 -1
- package/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.ts +16 -2
- package/src/internal/builtin-plugins/solidity/build-system/resolver/error-messages.ts +19 -5
- package/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.ts +103 -29
- package/src/internal/builtin-plugins/solidity/type-extensions.ts +28 -0
- package/src/internal/builtin-plugins/solidity-test/config.ts +1 -0
- package/src/internal/builtin-plugins/solidity-test/type-extensions.ts +1 -0
- package/src/internal/cli/error-handler.ts +18 -0
- package/src/internal/cli/telemetry/sentry/reporter.ts +5 -0
- package/src/internal/cli/telemetry/sentry/transport.ts +1 -0
- package/src/internal/core/config-validation.ts +67 -18
- package/src/internal/core/tasks/builders.ts +174 -30
- package/src/internal/core/tasks/resolved-task.ts +31 -13
- package/src/internal/core/tasks/task-manager.ts +23 -5
- package/src/internal/core/tasks/validations.ts +40 -0
- package/src/internal/deprecated-module-imported-from-hardhat2-plugin.ts +12 -0
- package/src/internal/using-hardhat2-plugin-errors.ts +108 -0
- package/src/plugins.ts +16 -0
- package/src/types/index.ts +14 -0
- package/src/types/plugins.ts +2 -2
- package/src/types/solidity/errors.ts +22 -0
- package/src/types/tasks.ts +133 -36
- package/templates/hardhat-3/01-node-test-runner-viem/package.json +10 -10
- package/templates/hardhat-3/02-mocha-ethers/package.json +16 -16
- package/templates/hardhat-3/03-minimal/package.json +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { GasAnalyticsManager, GasMeasurement } from "./types.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { TableItem } from "@nomicfoundation/hardhat-utils/format";
|
|
3
3
|
|
|
4
4
|
import crypto from "node:crypto";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { formatTable } from "@nomicfoundation/hardhat-utils/format";
|
|
8
8
|
import {
|
|
9
9
|
ensureDir,
|
|
10
10
|
getAllFilesMatching,
|
|
@@ -142,8 +142,8 @@ export class GasAnalyticsManagerImplementation implements GasAnalyticsManager {
|
|
|
142
142
|
const stats: GasStats = {
|
|
143
143
|
min: Math.min(...gasValues),
|
|
144
144
|
max: Math.max(...gasValues),
|
|
145
|
-
avg:
|
|
146
|
-
median:
|
|
145
|
+
avg: Math.round(avg(gasValues)),
|
|
146
|
+
median: Math.round(median(gasValues)),
|
|
147
147
|
calls: gasValues.length,
|
|
148
148
|
};
|
|
149
149
|
|
|
@@ -209,7 +209,7 @@ export class GasAnalyticsManagerImplementation implements GasAnalyticsManager {
|
|
|
209
209
|
public _generateGasStatsReport(
|
|
210
210
|
gasStatsByContract: GasStatsByContract,
|
|
211
211
|
): string {
|
|
212
|
-
const rows:
|
|
212
|
+
const rows: TableItem[] = [];
|
|
213
213
|
|
|
214
214
|
if (gasStatsByContract.size > 0) {
|
|
215
215
|
rows.push({ type: "title", text: chalk.bold("Gas Usage Statistics") });
|
|
@@ -279,7 +279,7 @@ export class GasAnalyticsManagerImplementation implements GasAnalyticsManager {
|
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
-
return
|
|
282
|
+
return formatTable(rows);
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
285
|
|
|
@@ -332,8 +332,3 @@ export function findDuplicates<T>(arr: T[]): T[] {
|
|
|
332
332
|
|
|
333
333
|
return [...duplicates];
|
|
334
334
|
}
|
|
335
|
-
|
|
336
|
-
export function roundTo(value: number, decimals: number): number {
|
|
337
|
-
const factor = 10 ** decimals;
|
|
338
|
-
return Math.round(value * factor) / factor;
|
|
339
|
-
}
|
|
@@ -38,33 +38,77 @@ export async function extendUserConfig(
|
|
|
38
38
|
const networks: Record<string, NetworkUserConfig> =
|
|
39
39
|
extendedConfig.networks ?? {};
|
|
40
40
|
|
|
41
|
-
const localhostConfig:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
41
|
+
const localhostConfig: NetworkUserConfig | undefined = networks.localhost;
|
|
42
|
+
const defaultConfig: NetworkUserConfig | undefined = networks.default;
|
|
43
|
+
const nodeConfig: NetworkUserConfig | undefined = networks.node;
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
let extendedLocalhostConfig: NetworkUserConfig;
|
|
46
|
+
if (
|
|
47
|
+
localhostConfig === undefined ||
|
|
48
|
+
localhostConfig.type === undefined ||
|
|
49
|
+
localhostConfig.type === "http"
|
|
50
|
+
) {
|
|
51
|
+
extendedLocalhostConfig = {
|
|
52
|
+
url: "http://localhost:8545",
|
|
53
|
+
type: "http",
|
|
54
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
55
|
+
-- We cast it here because otherwise TS complains that some fields are
|
|
56
|
+
always overwritten, which is not true for js incomplete configs. */
|
|
57
|
+
...(localhostConfig as Partial<HttpNetworkUserConfig>),
|
|
58
|
+
};
|
|
59
|
+
} else {
|
|
60
|
+
extendedLocalhostConfig = localhostConfig;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const defaultEdrNetworkConfigValues = {
|
|
64
|
+
chainId: 31337,
|
|
65
|
+
gas: "auto",
|
|
66
|
+
gasMultiplier: 1,
|
|
67
|
+
gasPrice: "auto",
|
|
68
|
+
type: "edr-simulated",
|
|
69
|
+
} as const;
|
|
70
|
+
|
|
71
|
+
let extendedDefaultConfig: NetworkUserConfig;
|
|
72
|
+
if (
|
|
73
|
+
defaultConfig === undefined ||
|
|
74
|
+
defaultConfig.type === undefined ||
|
|
75
|
+
defaultConfig.type === "edr-simulated"
|
|
76
|
+
) {
|
|
77
|
+
extendedDefaultConfig = {
|
|
78
|
+
...defaultEdrNetworkConfigValues,
|
|
79
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
80
|
+
-- We cast it here because otherwise TS complains that some fields are
|
|
81
|
+
always overwritten, which is not true for js incomplete configs. */
|
|
82
|
+
...(defaultConfig as Partial<EdrNetworkUserConfig>),
|
|
83
|
+
};
|
|
84
|
+
} else {
|
|
85
|
+
extendedDefaultConfig = defaultConfig;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let extendedNodeConfig: NetworkUserConfig;
|
|
89
|
+
if (
|
|
90
|
+
nodeConfig === undefined ||
|
|
91
|
+
nodeConfig.type === undefined ||
|
|
92
|
+
nodeConfig.type === "edr-simulated"
|
|
93
|
+
) {
|
|
94
|
+
extendedNodeConfig = {
|
|
95
|
+
...defaultEdrNetworkConfigValues,
|
|
96
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
97
|
+
-- We cast it here because otherwise TS complains that url and http will
|
|
98
|
+
be always overwritten, which is not true for js incomplete configs. */
|
|
99
|
+
...(nodeConfig as Partial<EdrNetworkUserConfig>),
|
|
100
|
+
};
|
|
101
|
+
} else {
|
|
102
|
+
extendedNodeConfig = nodeConfig;
|
|
103
|
+
}
|
|
50
104
|
|
|
51
105
|
return {
|
|
52
106
|
...extendedConfig,
|
|
53
107
|
networks: {
|
|
54
108
|
...networks,
|
|
55
|
-
localhost:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
type: "http",
|
|
59
|
-
},
|
|
60
|
-
[DEFAULT_NETWORK_NAME]: {
|
|
61
|
-
chainId: 31337,
|
|
62
|
-
gas: "auto",
|
|
63
|
-
gasMultiplier: 1,
|
|
64
|
-
gasPrice: "auto",
|
|
65
|
-
...defaultConfig,
|
|
66
|
-
type: "edr-simulated",
|
|
67
|
-
},
|
|
109
|
+
localhost: extendedLocalhostConfig,
|
|
110
|
+
[DEFAULT_NETWORK_NAME]: extendedDefaultConfig,
|
|
111
|
+
node: extendedNodeConfig,
|
|
68
112
|
},
|
|
69
113
|
};
|
|
70
114
|
}
|
|
@@ -344,6 +344,15 @@ function refineEdrNetworkUserConfig(
|
|
|
344
344
|
{ defaultChainType = GENERIC_CHAIN_TYPE, networks = {} }: HardhatUserConfig,
|
|
345
345
|
ctx: RefinementCtx,
|
|
346
346
|
): void {
|
|
347
|
+
const nodeNetwork = networks.node;
|
|
348
|
+
if (nodeNetwork !== undefined && nodeNetwork.type !== "edr-simulated") {
|
|
349
|
+
ctx.addIssue({
|
|
350
|
+
code: z.ZodIssueCode.custom,
|
|
351
|
+
path: ["networks", "node", "type"],
|
|
352
|
+
message: "The node network type must be 'edr-simulated'",
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
|
|
347
356
|
for (const [networkName, network] of Object.entries(networks)) {
|
|
348
357
|
if (network.type === "edr-simulated") {
|
|
349
358
|
const { chainType, hardfork, minGasPrice, initialBaseFeePerGas } =
|
|
@@ -12,7 +12,6 @@ import { ensureDir, exists } from "@nomicfoundation/hardhat-utils/fs";
|
|
|
12
12
|
import chalk from "chalk";
|
|
13
13
|
import debug from "debug";
|
|
14
14
|
|
|
15
|
-
import { DEFAULT_NETWORK_NAME } from "../../constants.js";
|
|
16
15
|
import { isSupportedChainType } from "../../edr/chain-type.js";
|
|
17
16
|
import { BUILD_INFO_DIR_NAME } from "../artifacts/artifact-manager.js";
|
|
18
17
|
import { EdrProvider } from "../network-manager/edr/edr-provider.js";
|
|
@@ -42,7 +41,7 @@ const nodeAction: NewTaskActionFunction<NodeActionArguments> = async (
|
|
|
42
41
|
const network =
|
|
43
42
|
hre.globalOptions.network !== undefined
|
|
44
43
|
? hre.globalOptions.network
|
|
45
|
-
:
|
|
44
|
+
: "node";
|
|
46
45
|
|
|
47
46
|
if (!(network in hre.config.networks)) {
|
|
48
47
|
throw new HardhatError(HardhatError.ERRORS.CORE.NETWORK.NETWORK_NOT_FOUND, {
|
|
@@ -64,6 +63,7 @@ const nodeAction: NewTaskActionFunction<NodeActionArguments> = async (
|
|
|
64
63
|
} = {
|
|
65
64
|
network,
|
|
66
65
|
};
|
|
66
|
+
|
|
67
67
|
// NOTE: We create an empty network config override here. We add to it based
|
|
68
68
|
// on the result of arguments parsing. We can expand the list of arguments
|
|
69
69
|
// as much as needed.
|
|
@@ -418,6 +418,7 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem {
|
|
|
418
418
|
rootFilePaths.toSorted(), // We sort them to have a deterministic order
|
|
419
419
|
this.#options.projectRoot,
|
|
420
420
|
readSourceFileFactory(this.#hooks),
|
|
421
|
+
this.#hooks,
|
|
421
422
|
);
|
|
422
423
|
|
|
423
424
|
const { buildProfileName, buildProfile } = this.#getBuildProfile(
|
|
@@ -152,13 +152,8 @@ export class CompilerDownloaderImplementation implements CompilerDownloader {
|
|
|
152
152
|
readonly #platform: CompilerPlatform;
|
|
153
153
|
readonly #compilersDir: string;
|
|
154
154
|
readonly #downloadFunction: typeof download;
|
|
155
|
+
readonly #mutexCompilerList: MultiProcessMutex;
|
|
155
156
|
|
|
156
|
-
readonly #mutexCompiler = new MultiProcessMutex("compiler-download");
|
|
157
|
-
readonly #mutexCompilerList = new MultiProcessMutex("compiler-download-list");
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Use CompilerDownloader.getConcurrencySafeDownloader instead
|
|
161
|
-
*/
|
|
162
157
|
constructor(
|
|
163
158
|
platform: CompilerPlatform,
|
|
164
159
|
compilersDir: string,
|
|
@@ -166,6 +161,9 @@ export class CompilerDownloaderImplementation implements CompilerDownloader {
|
|
|
166
161
|
) {
|
|
167
162
|
this.#platform = platform;
|
|
168
163
|
this.#compilersDir = compilersDir;
|
|
164
|
+
this.#mutexCompilerList = new MultiProcessMutex(
|
|
165
|
+
path.join(compilersDir, "compiler-download-list"),
|
|
166
|
+
);
|
|
169
167
|
this.#downloadFunction = downloadFunction;
|
|
170
168
|
}
|
|
171
169
|
|
|
@@ -200,11 +198,16 @@ export class CompilerDownloaderImplementation implements CompilerDownloader {
|
|
|
200
198
|
}
|
|
201
199
|
|
|
202
200
|
public async downloadCompiler(version: string): Promise<boolean> {
|
|
203
|
-
//
|
|
204
|
-
//
|
|
205
|
-
//
|
|
206
|
-
//
|
|
207
|
-
|
|
201
|
+
// A per-version mutex ensures that only one process at a time can download a given compiler version,
|
|
202
|
+
// while still allowing different compiler versions to be downloaded in parallel.
|
|
203
|
+
// Without the mutex, a concurrent process might check whether a version exists, incorrectly
|
|
204
|
+
// find it missing (because another process is still downloading it), and start a redundant download.
|
|
205
|
+
|
|
206
|
+
const mutex = new MultiProcessMutex(
|
|
207
|
+
path.join(this.#compilersDir, `compiler-download-${version}`),
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
return mutex.use(async () => {
|
|
208
211
|
const isCompilerDownloaded = await this.isCompilerDownloaded(version);
|
|
209
212
|
|
|
210
213
|
if (isCompilerDownloaded === true) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { RemappingsReaderFunction } from "./resolver/remapped-npm-packages-graph.js";
|
|
2
|
+
import type { HookManager } from "../../../../types/hooks.js";
|
|
1
3
|
import type { ResolvedFile } from "../../../../types/solidity/resolved-file.js";
|
|
2
4
|
|
|
3
5
|
import { HardhatError } from "@nomicfoundation/hardhat-errors";
|
|
@@ -17,8 +19,28 @@ export async function buildDependencyGraph(
|
|
|
17
19
|
rootFiles: string[],
|
|
18
20
|
projectRoot: string,
|
|
19
21
|
readFile: (absPath: string) => Promise<string>,
|
|
22
|
+
hookManager: HookManager,
|
|
20
23
|
): Promise<DependencyGraphImplementation> {
|
|
21
|
-
|
|
24
|
+
// Create the wrapper function that captures the hook manager
|
|
25
|
+
const remappingsReader: RemappingsReaderFunction = (
|
|
26
|
+
packageName,
|
|
27
|
+
packageVersion,
|
|
28
|
+
packagePath,
|
|
29
|
+
defaultBehavior,
|
|
30
|
+
) =>
|
|
31
|
+
hookManager.runHandlerChain(
|
|
32
|
+
"solidity",
|
|
33
|
+
"readNpmPackageRemappings",
|
|
34
|
+
[packageName, packageVersion, packagePath],
|
|
35
|
+
async (_context, name, version, path) =>
|
|
36
|
+
defaultBehavior(name, version, path),
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const resolver = await ResolverImplementation.create(
|
|
40
|
+
projectRoot,
|
|
41
|
+
readFile,
|
|
42
|
+
remappingsReader,
|
|
43
|
+
);
|
|
22
44
|
|
|
23
45
|
const dependencyGraph = new DependencyGraphImplementation();
|
|
24
46
|
|
|
@@ -38,6 +38,7 @@ import { parseNpmDirectImport } from "./npm-module-parsing.js";
|
|
|
38
38
|
import {
|
|
39
39
|
isResolvedUserRemapping,
|
|
40
40
|
RemappedNpmPackagesGraphImplementation,
|
|
41
|
+
type RemappingsReaderFunction,
|
|
41
42
|
} from "./remapped-npm-packages-graph.js";
|
|
42
43
|
import { applyValidRemapping, formatRemapping } from "./remappings.js";
|
|
43
44
|
import {
|
|
@@ -86,14 +87,18 @@ export class ResolverImplementation implements Resolver {
|
|
|
86
87
|
*
|
|
87
88
|
* @param projectRoot The absolute path to the Hardhat project root.
|
|
88
89
|
* @param readUtf8File A function that reads a UTF-8 file.
|
|
90
|
+
* @param remappingsReader Optional function to read remappings from packages.
|
|
89
91
|
* @returns The resolver or the user remapping errors found.
|
|
90
92
|
*/
|
|
91
93
|
public static async create(
|
|
92
94
|
projectRoot: string,
|
|
93
95
|
readUtf8File: (absPath: string) => Promise<string>,
|
|
96
|
+
remappingsReader?: RemappingsReaderFunction,
|
|
94
97
|
): Promise<Resolver> {
|
|
95
|
-
const map =
|
|
96
|
-
|
|
98
|
+
const map = await RemappedNpmPackagesGraphImplementation.create(
|
|
99
|
+
projectRoot,
|
|
100
|
+
remappingsReader,
|
|
101
|
+
);
|
|
97
102
|
|
|
98
103
|
return new ResolverImplementation(projectRoot, map, readUtf8File);
|
|
99
104
|
}
|
|
@@ -691,6 +696,13 @@ export class ResolverImplementation implements Resolver {
|
|
|
691
696
|
);
|
|
692
697
|
|
|
693
698
|
if (dependencyResolution === undefined) {
|
|
699
|
+
// Check if the from file's package has foundry.toml
|
|
700
|
+
const foundryTomlPath = path.join(
|
|
701
|
+
from.package.rootFsPath,
|
|
702
|
+
"foundry.toml",
|
|
703
|
+
);
|
|
704
|
+
const fromHasFoundryToml = await exists(foundryTomlPath);
|
|
705
|
+
|
|
694
706
|
return {
|
|
695
707
|
success: false,
|
|
696
708
|
error: {
|
|
@@ -698,6 +710,7 @@ export class ResolverImplementation implements Resolver {
|
|
|
698
710
|
fromFsPath: from.fsPath,
|
|
699
711
|
importPath,
|
|
700
712
|
installationName: parsedDirectImport.package,
|
|
713
|
+
importerPackageHasFoundryToml: fromHasFoundryToml,
|
|
701
714
|
},
|
|
702
715
|
};
|
|
703
716
|
}
|
|
@@ -1098,6 +1111,7 @@ export class ResolverImplementation implements Resolver {
|
|
|
1098
1111
|
type: RootResolutionErrorType.NPM_ROOT_FILE_OF_UNINSTALLED_PACKAGE,
|
|
1099
1112
|
npmModule,
|
|
1100
1113
|
installationName: error.installationName,
|
|
1114
|
+
projectHasFoundryToml: error.importerPackageHasFoundryToml,
|
|
1101
1115
|
};
|
|
1102
1116
|
}
|
|
1103
1117
|
case ImportResolutionErrorType.IMPORT_WITH_REMAPPING_ERRORS: {
|
|
@@ -57,7 +57,14 @@ Note that the npm module is being remapped by ${formatRemappingReference(error.u
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
case RootResolutionErrorType.NPM_ROOT_FILE_OF_UNINSTALLED_PACKAGE: {
|
|
60
|
-
|
|
60
|
+
const baseMessage = `The package "${error.installationName}" is not installed.`;
|
|
61
|
+
if (error.projectHasFoundryToml === true) {
|
|
62
|
+
return `${baseMessage}
|
|
63
|
+
|
|
64
|
+
Your project has a foundry.toml, and you may need to install the "@nomicfoundation/hardhat-foundry" plugin.
|
|
65
|
+
Learn more about Hardhat's Foundry compatibility here: https://hardhat.org/foundry-compatibility`;
|
|
66
|
+
}
|
|
67
|
+
return baseMessage;
|
|
61
68
|
}
|
|
62
69
|
|
|
63
70
|
case RootResolutionErrorType.NPM_ROOT_FILE_RESOLUTION_WITH_REMAPPING_ERRORS: {
|
|
@@ -107,13 +114,13 @@ export function formatImportResolutionError(
|
|
|
107
114
|
}
|
|
108
115
|
|
|
109
116
|
case ImportResolutionErrorType.ILLEGAL_RELATIVE_IMPORT: {
|
|
110
|
-
return "The import has too many '../'
|
|
117
|
+
return "The import has too many '../' and is trying to leave its package.";
|
|
111
118
|
}
|
|
112
119
|
|
|
113
120
|
case ImportResolutionErrorType.RELATIVE_IMPORT_INTO_NODE_MODULES: {
|
|
114
121
|
return `You are trying to import a file from your node_modules directory with its file system path.
|
|
115
122
|
|
|
116
|
-
You should write your
|
|
123
|
+
You should write your imports into npm modules just as you would do in JavaScript files.`;
|
|
117
124
|
}
|
|
118
125
|
|
|
119
126
|
case ImportResolutionErrorType.IMPORT_WITH_INVALID_NPM_SYNTAX: {
|
|
@@ -121,7 +128,14 @@ You should write your the path of your imports into npm modules just as you woul
|
|
|
121
128
|
}
|
|
122
129
|
|
|
123
130
|
case ImportResolutionErrorType.IMPORT_OF_UNINSTALLED_PACKAGE: {
|
|
124
|
-
|
|
131
|
+
const baseMessage = `The package "${error.installationName}" is not installed.`;
|
|
132
|
+
if (error.importerPackageHasFoundryToml === true) {
|
|
133
|
+
return `${baseMessage}
|
|
134
|
+
|
|
135
|
+
The file importing this package is inside a Foundry project (foundry.toml detected), and you may need to install the "@nomicfoundation/hardhat-foundry" plugin.
|
|
136
|
+
Learn more about Hardhat's Foundry compatibility here: https://hardhat.org/foundry-compatibility`;
|
|
137
|
+
}
|
|
138
|
+
return baseMessage;
|
|
125
139
|
}
|
|
126
140
|
|
|
127
141
|
case ImportResolutionErrorType.IMPORT_WITH_REMAPPING_ERRORS: {
|
|
@@ -148,7 +162,7 @@ If you still want to be able to do it, try adding this remapping "${error.sugges
|
|
|
148
162
|
? "the package"
|
|
149
163
|
: "the project";
|
|
150
164
|
|
|
151
|
-
const message = `The file ${error.packageExportsResolvedSubpath ?? error.subpath} doesn't exist within ${packageOrProject}.`;
|
|
165
|
+
const message = `The file "${error.packageExportsResolvedSubpath ?? error.subpath}" doesn't exist within ${packageOrProject}.`;
|
|
152
166
|
|
|
153
167
|
return formatResolutionErrorRemappingsOrPackageExportsNotes({
|
|
154
168
|
message,
|
package/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.ts
CHANGED
|
@@ -37,6 +37,17 @@ import { UserRemappingType } from "./types.js";
|
|
|
37
37
|
|
|
38
38
|
const HARDHAT_PROJECT_INPUT_SOURCE_NAME_ROOT = "project";
|
|
39
39
|
|
|
40
|
+
export type RemappingsReaderFunction = (
|
|
41
|
+
packageName: string,
|
|
42
|
+
packageVersion: string,
|
|
43
|
+
packagePath: string,
|
|
44
|
+
defaultBehavior: (
|
|
45
|
+
name: string,
|
|
46
|
+
version: string,
|
|
47
|
+
path: string,
|
|
48
|
+
) => Promise<Array<{ remappings: string[]; source: string }>>,
|
|
49
|
+
) => Promise<Array<{ remappings: string[]; source: string }>>;
|
|
50
|
+
|
|
40
51
|
export function isResolvedUserRemapping(
|
|
41
52
|
remapping: Remapping | ResolvedUserRemapping,
|
|
42
53
|
): remapping is ResolvedUserRemapping {
|
|
@@ -55,6 +66,11 @@ export class RemappedNpmPackagesGraphImplementation
|
|
|
55
66
|
*/
|
|
56
67
|
readonly #hardhatProjectPackage: ResolvedNpmPackage;
|
|
57
68
|
|
|
69
|
+
/**
|
|
70
|
+
* The remappings reader function to use when reading package remappings.
|
|
71
|
+
*/
|
|
72
|
+
readonly #remappingsReader: RemappingsReaderFunction;
|
|
73
|
+
|
|
58
74
|
/**
|
|
59
75
|
* This is a map of all the npm packages. Every package that has been
|
|
60
76
|
* loaded by this class, is present in this map.
|
|
@@ -104,6 +120,12 @@ export class RemappedNpmPackagesGraphImplementation
|
|
|
104
120
|
|
|
105
121
|
public static async create(
|
|
106
122
|
projectRootPath: string,
|
|
123
|
+
remappingsReader: RemappingsReaderFunction = (
|
|
124
|
+
packageName,
|
|
125
|
+
packageVersion,
|
|
126
|
+
packagePath,
|
|
127
|
+
defaultBehavior,
|
|
128
|
+
) => defaultBehavior(packageName, packageVersion, packagePath),
|
|
107
129
|
): Promise<RemappedNpmPackagesGraphImplementation> {
|
|
108
130
|
const projectPackageJson = await readJsonFile<PackageJson>(
|
|
109
131
|
path.join(projectRootPath, "package.json"),
|
|
@@ -117,11 +139,18 @@ export class RemappedNpmPackagesGraphImplementation
|
|
|
117
139
|
inputSourceNameRoot: HARDHAT_PROJECT_INPUT_SOURCE_NAME_ROOT,
|
|
118
140
|
};
|
|
119
141
|
|
|
120
|
-
return new RemappedNpmPackagesGraphImplementation(
|
|
142
|
+
return new RemappedNpmPackagesGraphImplementation(
|
|
143
|
+
resolvedNpmPackage,
|
|
144
|
+
remappingsReader,
|
|
145
|
+
);
|
|
121
146
|
}
|
|
122
147
|
|
|
123
|
-
private constructor(
|
|
148
|
+
private constructor(
|
|
149
|
+
hardhatProjectPackage: ResolvedNpmPackage,
|
|
150
|
+
remappingsReader: RemappingsReaderFunction,
|
|
151
|
+
) {
|
|
124
152
|
this.#hardhatProjectPackage = hardhatProjectPackage;
|
|
153
|
+
this.#remappingsReader = remappingsReader;
|
|
125
154
|
this.#insertNewPackage(hardhatProjectPackage);
|
|
126
155
|
}
|
|
127
156
|
|
|
@@ -397,41 +426,88 @@ export class RemappedNpmPackagesGraphImplementation
|
|
|
397
426
|
UserRemappingError[]
|
|
398
427
|
>
|
|
399
428
|
> {
|
|
400
|
-
const
|
|
429
|
+
const allRemappings = await this.#remappingsReader(
|
|
430
|
+
npmPackage.name,
|
|
431
|
+
npmPackage.version,
|
|
401
432
|
npmPackage.rootFsPath,
|
|
402
|
-
(
|
|
403
|
-
|
|
433
|
+
async (_packageName, _packageVersion, packagePath) =>
|
|
434
|
+
this.#defaultReadPackageRemappings(packagePath),
|
|
404
435
|
);
|
|
405
436
|
|
|
406
|
-
|
|
407
|
-
|
|
437
|
+
return this.#parseAndDeduplicateRemappings(npmPackage, allRemappings);
|
|
438
|
+
}
|
|
408
439
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
440
|
+
/**
|
|
441
|
+
* The default behavior of reading all the remappings.txt files in a package.
|
|
442
|
+
* @param packagePath The fs path to the root of the package.
|
|
443
|
+
* @returns An array with one entry per remappings.txt file, with the
|
|
444
|
+
* contents of the file and the fs path to the file.
|
|
445
|
+
*/
|
|
446
|
+
async #defaultReadPackageRemappings(
|
|
447
|
+
packagePath: string,
|
|
448
|
+
): Promise<Array<{ remappings: string[]; source: string }>> {
|
|
449
|
+
const remappingsTxtFiles = await getAllFilesMatching(
|
|
450
|
+
packagePath,
|
|
451
|
+
(f) => path.basename(f) === "remappings.txt",
|
|
452
|
+
(f) => !f.endsWith("node_modules"),
|
|
453
|
+
);
|
|
412
454
|
|
|
413
|
-
|
|
455
|
+
const results: Array<{ remappings: string[]; source: string }> = [];
|
|
456
|
+
for (const file of remappingsTxtFiles) {
|
|
457
|
+
const contents = await readUtf8File(file);
|
|
458
|
+
const lines = contents
|
|
414
459
|
.split("\n")
|
|
415
460
|
.map((line) => line.trim())
|
|
416
|
-
.filter((line) => line !== "")
|
|
417
|
-
|
|
461
|
+
.filter((line) => line !== "" && !line.startsWith("#"));
|
|
462
|
+
results.push({ remappings: lines, source: file });
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return results;
|
|
466
|
+
}
|
|
418
467
|
|
|
419
|
-
|
|
420
|
-
|
|
468
|
+
/**
|
|
469
|
+
* Parses and deduplicates by "context:prefix" all the remappings from the
|
|
470
|
+
* package.
|
|
471
|
+
*
|
|
472
|
+
* @param npmPackage The npm package.
|
|
473
|
+
* @param allRemappings An array with all the remappings.txt files in the
|
|
474
|
+
* package and their content.
|
|
475
|
+
* @returns A result with the parsed and deduplicated remappings, or an error
|
|
476
|
+
* if there was a problem parsing any of them.
|
|
477
|
+
*/
|
|
478
|
+
#parseAndDeduplicateRemappings(
|
|
479
|
+
npmPackage: ResolvedNpmPackage,
|
|
480
|
+
allRemappings: Array<{ remappings: string[]; source: string }>,
|
|
481
|
+
): Result<
|
|
482
|
+
Array<LocalUserRemapping | UnresolvedNpmUserRemapping>,
|
|
483
|
+
UserRemappingError[]
|
|
484
|
+
> {
|
|
485
|
+
const remappings: Array<LocalUserRemapping | UnresolvedNpmUserRemapping> =
|
|
486
|
+
[];
|
|
487
|
+
const errors: UserRemappingError[] = [];
|
|
488
|
+
const seen = new Set<string>(); // Track by "context:prefix"
|
|
489
|
+
|
|
490
|
+
for (const { remappings: remappingStrings, source } of allRemappings) {
|
|
491
|
+
for (const remappingString of remappingStrings) {
|
|
492
|
+
const result = this.#parseUserRemapping(
|
|
421
493
|
npmPackage,
|
|
422
|
-
|
|
423
|
-
|
|
494
|
+
source,
|
|
495
|
+
remappingString,
|
|
424
496
|
);
|
|
425
497
|
|
|
426
498
|
if (!result.success) {
|
|
427
499
|
errors.push(result.error);
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (result.value === undefined) {
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
434
506
|
|
|
507
|
+
// Deduplicate by (context + prefix) - first occurrence wins
|
|
508
|
+
const key = `${result.value.context}:${result.value.prefix}`;
|
|
509
|
+
if (!seen.has(key)) {
|
|
510
|
+
seen.add(key);
|
|
435
511
|
remappings.push(result.value);
|
|
436
512
|
}
|
|
437
513
|
}
|
|
@@ -454,15 +530,13 @@ export class RemappedNpmPackagesGraphImplementation
|
|
|
454
530
|
* @returns The parsed user remapping, or undefined if it should be ignored.
|
|
455
531
|
* If the parsing and validation fails, an error is returned.
|
|
456
532
|
*/
|
|
457
|
-
|
|
533
|
+
#parseUserRemapping(
|
|
458
534
|
npmPackage: ResolvedNpmPackage,
|
|
459
535
|
sourceOfTheRemapping: string,
|
|
460
536
|
remappingString: string,
|
|
461
|
-
):
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
UserRemappingError
|
|
465
|
-
>
|
|
537
|
+
): Result<
|
|
538
|
+
LocalUserRemapping | UnresolvedNpmUserRemapping | undefined,
|
|
539
|
+
UserRemappingError
|
|
466
540
|
> {
|
|
467
541
|
// We first parse the remapping string and validate that it doesn't have
|
|
468
542
|
// a context starting with `npm/`, and that the prefix and targets end in /.
|
|
@@ -242,5 +242,33 @@ declare module "../../../types/hooks.js" {
|
|
|
242
242
|
nextSolcConfig: SolcConfig,
|
|
243
243
|
) => Promise<CompilerOutput>,
|
|
244
244
|
): Promise<CompilerOutput>;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Provide a handler for this hook to supply remappings for npm packages.
|
|
248
|
+
*
|
|
249
|
+
* This hook is called when the resolver needs to read remappings for a package.
|
|
250
|
+
* Handlers can provide remappings from alternative sources (e.g., foundry.toml)
|
|
251
|
+
* in addition to the default remappings.txt files.
|
|
252
|
+
*
|
|
253
|
+
* @param context The hook context.
|
|
254
|
+
* @param packageName The name of the npm package.
|
|
255
|
+
* @param packageVersion The version of the npm package.
|
|
256
|
+
* @param packagePath The absolute filesystem path to the package root.
|
|
257
|
+
* @param next A function to get remappings from other sources (including default behavior).
|
|
258
|
+
* @returns An array of remapping sources, each containing an array of remapping strings
|
|
259
|
+
* and the source path they came from.
|
|
260
|
+
*/
|
|
261
|
+
readNpmPackageRemappings: (
|
|
262
|
+
context: HookContext,
|
|
263
|
+
packageName: string,
|
|
264
|
+
packageVersion: string,
|
|
265
|
+
packagePath: string,
|
|
266
|
+
next: (
|
|
267
|
+
nextContext: HookContext,
|
|
268
|
+
nextPackageName: string,
|
|
269
|
+
nextPackageVersion: string,
|
|
270
|
+
nextPackagePath: string,
|
|
271
|
+
) => Promise<Array<{ remappings: string[]; source: string }>>,
|
|
272
|
+
) => Promise<Array<{ remappings: string[]; source: string }>>;
|
|
245
273
|
}
|
|
246
274
|
}
|
|
@@ -44,6 +44,7 @@ const solidityTestUserConfigType = z.object({
|
|
|
44
44
|
coinbase: z.string().startsWith("0x").optional(),
|
|
45
45
|
blockTimestamp: z.bigint().optional(),
|
|
46
46
|
prevRandao: z.bigint().optional(),
|
|
47
|
+
gasLimit: z.bigint().optional(),
|
|
47
48
|
blockGasLimit: z.bigint().or(z.literal(false)).optional(),
|
|
48
49
|
fuzz: z
|
|
49
50
|
.object({
|