hardhat 3.4.5 → 3.5.0

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.
Files changed (215) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/src/config.d.ts +0 -1
  3. package/dist/src/config.d.ts.map +1 -1
  4. package/dist/src/config.js.map +1 -1
  5. package/dist/src/hre.d.ts +0 -1
  6. package/dist/src/hre.d.ts.map +1 -1
  7. package/dist/src/hre.js.map +1 -1
  8. package/dist/src/index.d.ts +0 -1
  9. package/dist/src/index.d.ts.map +1 -1
  10. package/dist/src/index.js.map +1 -1
  11. package/dist/src/internal/builtin-global-options.d.ts.map +1 -1
  12. package/dist/src/internal/builtin-global-options.js +1 -1
  13. package/dist/src/internal/builtin-global-options.js.map +1 -1
  14. package/dist/src/internal/builtin-plugins/gas-analytics/snapshot-cheatcodes.d.ts +21 -0
  15. package/dist/src/internal/builtin-plugins/gas-analytics/snapshot-cheatcodes.d.ts.map +1 -1
  16. package/dist/src/internal/builtin-plugins/gas-analytics/snapshot-cheatcodes.js +49 -1
  17. package/dist/src/internal/builtin-plugins/gas-analytics/snapshot-cheatcodes.js.map +1 -1
  18. package/dist/src/internal/builtin-plugins/gas-analytics/tasks/solidity-test/task-action.d.ts +2 -1
  19. package/dist/src/internal/builtin-plugins/gas-analytics/tasks/solidity-test/task-action.d.ts.map +1 -1
  20. package/dist/src/internal/builtin-plugins/gas-analytics/tasks/solidity-test/task-action.js +12 -2
  21. package/dist/src/internal/builtin-plugins/gas-analytics/tasks/solidity-test/task-action.js.map +1 -1
  22. package/dist/src/internal/builtin-plugins/network-manager/config-resolution.d.ts.map +1 -1
  23. package/dist/src/internal/builtin-plugins/network-manager/config-resolution.js +9 -2
  24. package/dist/src/internal/builtin-plugins/network-manager/config-resolution.js.map +1 -1
  25. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-constants.d.ts +1 -0
  26. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-constants.d.ts.map +1 -1
  27. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-constants.js +1 -0
  28. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-constants.js.map +1 -1
  29. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-provider.d.ts.map +1 -1
  30. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-provider.js +25 -5
  31. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-provider.js.map +1 -1
  32. package/dist/src/internal/builtin-plugins/network-manager/edr/utils/convert-to-edr.d.ts +16 -0
  33. package/dist/src/internal/builtin-plugins/network-manager/edr/utils/convert-to-edr.d.ts.map +1 -1
  34. package/dist/src/internal/builtin-plugins/network-manager/edr/utils/convert-to-edr.js +28 -1
  35. package/dist/src/internal/builtin-plugins/network-manager/edr/utils/convert-to-edr.js.map +1 -1
  36. package/dist/src/internal/builtin-plugins/network-manager/network-manager.d.ts.map +1 -1
  37. package/dist/src/internal/builtin-plugins/network-manager/network-manager.js +2 -6
  38. package/dist/src/internal/builtin-plugins/network-manager/network-manager.js.map +1 -1
  39. package/dist/src/internal/builtin-plugins/network-manager/type-extensions/config.d.ts +5 -3
  40. package/dist/src/internal/builtin-plugins/network-manager/type-extensions/config.d.ts.map +1 -1
  41. package/dist/src/internal/builtin-plugins/network-manager/type-validation.d.ts.map +1 -1
  42. package/dist/src/internal/builtin-plugins/network-manager/type-validation.js +3 -1
  43. package/dist/src/internal/builtin-plugins/network-manager/type-validation.js.map +1 -1
  44. package/dist/src/internal/builtin-plugins/network-manager/utils/apply-coverage-network-overrides.d.ts +18 -0
  45. package/dist/src/internal/builtin-plugins/network-manager/utils/apply-coverage-network-overrides.d.ts.map +1 -0
  46. package/dist/src/internal/builtin-plugins/network-manager/utils/apply-coverage-network-overrides.js +27 -0
  47. package/dist/src/internal/builtin-plugins/network-manager/utils/apply-coverage-network-overrides.js.map +1 -0
  48. package/dist/src/internal/builtin-plugins/node/json-rpc/handler.js +6 -5
  49. package/dist/src/internal/builtin-plugins/node/json-rpc/handler.js.map +1 -1
  50. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.d.ts.map +1 -1
  51. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.js +1 -1
  52. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.js.map +1 -1
  53. package/dist/src/internal/builtin-plugins/solidity/constants.d.ts +10 -0
  54. package/dist/src/internal/builtin-plugins/solidity/constants.d.ts.map +1 -1
  55. package/dist/src/internal/builtin-plugins/solidity/constants.js +10 -0
  56. package/dist/src/internal/builtin-plugins/solidity/constants.js.map +1 -1
  57. package/dist/src/internal/builtin-plugins/solidity/index.d.ts.map +1 -1
  58. package/dist/src/internal/builtin-plugins/solidity/index.js +1 -0
  59. package/dist/src/internal/builtin-plugins/solidity/index.js.map +1 -1
  60. package/dist/src/internal/builtin-plugins/solidity/tasks/compile.d.ts +9 -0
  61. package/dist/src/internal/builtin-plugins/solidity/tasks/compile.d.ts.map +1 -0
  62. package/dist/src/internal/builtin-plugins/solidity/tasks/compile.js +10 -0
  63. package/dist/src/internal/builtin-plugins/solidity/tasks/compile.js.map +1 -0
  64. package/dist/src/internal/builtin-plugins/solidity-test/config.d.ts +4 -3
  65. package/dist/src/internal/builtin-plugins/solidity-test/config.d.ts.map +1 -1
  66. package/dist/src/internal/builtin-plugins/solidity-test/config.js +55 -8
  67. package/dist/src/internal/builtin-plugins/solidity-test/config.js.map +1 -1
  68. package/dist/src/internal/builtin-plugins/solidity-test/eip712/ast-walker.d.ts +58 -0
  69. package/dist/src/internal/builtin-plugins/solidity-test/eip712/ast-walker.d.ts.map +1 -0
  70. package/dist/src/internal/builtin-plugins/solidity-test/eip712/ast-walker.js +226 -0
  71. package/dist/src/internal/builtin-plugins/solidity-test/eip712/ast-walker.js.map +1 -0
  72. package/dist/src/internal/builtin-plugins/solidity-test/eip712/canonicalize.d.ts +29 -0
  73. package/dist/src/internal/builtin-plugins/solidity-test/eip712/canonicalize.d.ts.map +1 -0
  74. package/dist/src/internal/builtin-plugins/solidity-test/eip712/canonicalize.js +244 -0
  75. package/dist/src/internal/builtin-plugins/solidity-test/eip712/canonicalize.js.map +1 -0
  76. package/dist/src/internal/builtin-plugins/solidity-test/eip712/glob.d.ts +7 -0
  77. package/dist/src/internal/builtin-plugins/solidity-test/eip712/glob.d.ts.map +1 -0
  78. package/dist/src/internal/builtin-plugins/solidity-test/eip712/glob.js +204 -0
  79. package/dist/src/internal/builtin-plugins/solidity-test/eip712/glob.js.map +1 -0
  80. package/dist/src/internal/builtin-plugins/solidity-test/eip712/index.d.ts +21 -0
  81. package/dist/src/internal/builtin-plugins/solidity-test/eip712/index.d.ts.map +1 -0
  82. package/dist/src/internal/builtin-plugins/solidity-test/eip712/index.js +77 -0
  83. package/dist/src/internal/builtin-plugins/solidity-test/eip712/index.js.map +1 -0
  84. package/dist/src/internal/builtin-plugins/solidity-test/helpers.d.ts +4 -3
  85. package/dist/src/internal/builtin-plugins/solidity-test/helpers.d.ts.map +1 -1
  86. package/dist/src/internal/builtin-plugins/solidity-test/helpers.js +20 -3
  87. package/dist/src/internal/builtin-plugins/solidity-test/helpers.js.map +1 -1
  88. package/dist/src/internal/builtin-plugins/solidity-test/task-action.d.ts.map +1 -1
  89. package/dist/src/internal/builtin-plugins/solidity-test/task-action.js +5 -1
  90. package/dist/src/internal/builtin-plugins/solidity-test/task-action.js.map +1 -1
  91. package/dist/src/internal/builtin-plugins/solidity-test/test-profiles.d.ts +2 -0
  92. package/dist/src/internal/builtin-plugins/solidity-test/test-profiles.d.ts.map +1 -0
  93. package/dist/src/internal/builtin-plugins/solidity-test/test-profiles.js +2 -0
  94. package/dist/src/internal/builtin-plugins/solidity-test/test-profiles.js.map +1 -0
  95. package/dist/src/internal/builtin-plugins/solidity-test/type-extensions.d.ts +91 -32
  96. package/dist/src/internal/builtin-plugins/solidity-test/type-extensions.d.ts.map +1 -1
  97. package/dist/src/internal/cli/init/init.d.ts +31 -6
  98. package/dist/src/internal/cli/init/init.d.ts.map +1 -1
  99. package/dist/src/internal/cli/init/init.js +121 -10
  100. package/dist/src/internal/cli/init/init.js.map +1 -1
  101. package/dist/src/internal/cli/main.d.ts.map +1 -1
  102. package/dist/src/internal/cli/main.js +41 -1
  103. package/dist/src/internal/cli/main.js.map +1 -1
  104. package/dist/src/types/arguments.d.ts +1 -0
  105. package/dist/src/types/arguments.d.ts.map +1 -1
  106. package/dist/src/types/arguments.js +1 -0
  107. package/dist/src/types/arguments.js.map +1 -1
  108. package/dist/src/types/artifacts.d.ts +1 -0
  109. package/dist/src/types/artifacts.d.ts.map +1 -1
  110. package/dist/src/types/artifacts.js +1 -1
  111. package/dist/src/types/artifacts.js.map +1 -1
  112. package/dist/src/types/builtin-plugin-type-extensions.d.ts +2 -0
  113. package/dist/src/types/builtin-plugin-type-extensions.d.ts.map +1 -0
  114. package/dist/src/types/builtin-plugin-type-extensions.js +2 -0
  115. package/dist/src/types/builtin-plugin-type-extensions.js.map +1 -0
  116. package/dist/src/types/config.d.ts +1 -0
  117. package/dist/src/types/config.d.ts.map +1 -1
  118. package/dist/src/types/config.js +1 -1
  119. package/dist/src/types/config.js.map +1 -1
  120. package/dist/src/types/global-options.d.ts +1 -0
  121. package/dist/src/types/global-options.d.ts.map +1 -1
  122. package/dist/src/types/global-options.js +1 -1
  123. package/dist/src/types/global-options.js.map +1 -1
  124. package/dist/src/types/hooks.d.ts +1 -0
  125. package/dist/src/types/hooks.d.ts.map +1 -1
  126. package/dist/src/types/hooks.js +1 -1
  127. package/dist/src/types/hooks.js.map +1 -1
  128. package/dist/src/types/hre.d.ts +1 -0
  129. package/dist/src/types/hre.d.ts.map +1 -1
  130. package/dist/src/types/hre.js +1 -1
  131. package/dist/src/types/hre.js.map +1 -1
  132. package/dist/src/types/index.d.ts +1 -0
  133. package/dist/src/types/index.d.ts.map +1 -1
  134. package/dist/src/types/index.js +1 -0
  135. package/dist/src/types/index.js.map +1 -1
  136. package/dist/src/types/network.d.ts +1 -0
  137. package/dist/src/types/network.d.ts.map +1 -1
  138. package/dist/src/types/network.js +1 -1
  139. package/dist/src/types/network.js.map +1 -1
  140. package/dist/src/types/plugins.d.ts +1 -1
  141. package/dist/src/types/plugins.d.ts.map +1 -1
  142. package/dist/src/types/plugins.js +1 -1
  143. package/dist/src/types/plugins.js.map +1 -1
  144. package/dist/src/types/providers.d.ts +1 -0
  145. package/dist/src/types/providers.d.ts.map +1 -1
  146. package/dist/src/types/providers.js +1 -1
  147. package/dist/src/types/providers.js.map +1 -1
  148. package/dist/src/types/solidity.d.ts +1 -0
  149. package/dist/src/types/solidity.d.ts.map +1 -1
  150. package/dist/src/types/solidity.js +1 -0
  151. package/dist/src/types/solidity.js.map +1 -1
  152. package/dist/src/types/tasks.d.ts +1 -0
  153. package/dist/src/types/tasks.d.ts.map +1 -1
  154. package/dist/src/types/tasks.js +1 -0
  155. package/dist/src/types/tasks.js.map +1 -1
  156. package/dist/src/types/test.d.ts +1 -0
  157. package/dist/src/types/test.d.ts.map +1 -1
  158. package/dist/src/types/test.js +1 -1
  159. package/dist/src/types/test.js.map +1 -1
  160. package/dist/src/types/user-interruptions.d.ts +1 -0
  161. package/dist/src/types/user-interruptions.d.ts.map +1 -1
  162. package/dist/src/types/user-interruptions.js +1 -1
  163. package/dist/src/types/user-interruptions.js.map +1 -1
  164. package/package.json +12 -11
  165. package/src/config.ts +0 -2
  166. package/src/hre.ts +0 -3
  167. package/src/index.ts +0 -3
  168. package/src/internal/builtin-global-options.ts +2 -1
  169. package/src/internal/builtin-plugins/gas-analytics/snapshot-cheatcodes.ts +90 -1
  170. package/src/internal/builtin-plugins/gas-analytics/tasks/solidity-test/task-action.ts +24 -2
  171. package/src/internal/builtin-plugins/network-manager/config-resolution.ts +11 -3
  172. package/src/internal/builtin-plugins/network-manager/edr/edr-constants.ts +2 -0
  173. package/src/internal/builtin-plugins/network-manager/edr/edr-provider.ts +38 -8
  174. package/src/internal/builtin-plugins/network-manager/edr/utils/convert-to-edr.ts +43 -1
  175. package/src/internal/builtin-plugins/network-manager/network-manager.ts +5 -6
  176. package/src/internal/builtin-plugins/network-manager/type-extensions/config.ts +5 -3
  177. package/src/internal/builtin-plugins/network-manager/type-validation.ts +7 -1
  178. package/src/internal/builtin-plugins/network-manager/utils/apply-coverage-network-overrides.ts +32 -0
  179. package/src/internal/builtin-plugins/node/json-rpc/handler.ts +7 -5
  180. package/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.ts +1 -2
  181. package/src/internal/builtin-plugins/solidity/constants.ts +11 -0
  182. package/src/internal/builtin-plugins/solidity/index.ts +1 -0
  183. package/src/internal/builtin-plugins/solidity/tasks/compile.ts +12 -0
  184. package/src/internal/builtin-plugins/solidity-test/config.ts +85 -12
  185. package/src/internal/builtin-plugins/solidity-test/eip712/ast-walker.ts +324 -0
  186. package/src/internal/builtin-plugins/solidity-test/eip712/canonicalize.ts +317 -0
  187. package/src/internal/builtin-plugins/solidity-test/eip712/glob.ts +225 -0
  188. package/src/internal/builtin-plugins/solidity-test/eip712/index.ts +120 -0
  189. package/src/internal/builtin-plugins/solidity-test/helpers.ts +28 -4
  190. package/src/internal/builtin-plugins/solidity-test/task-action.ts +12 -1
  191. package/src/internal/builtin-plugins/solidity-test/test-profiles.ts +1 -0
  192. package/src/internal/builtin-plugins/solidity-test/type-extensions.ts +100 -33
  193. package/src/internal/cli/init/init.ts +198 -16
  194. package/src/internal/cli/main.ts +64 -1
  195. package/src/types/arguments.ts +2 -0
  196. package/src/types/artifacts.ts +2 -0
  197. package/src/types/builtin-plugin-type-extensions.ts +15 -0
  198. package/src/types/config.ts +2 -0
  199. package/src/types/global-options.ts +2 -0
  200. package/src/types/hooks.ts +2 -0
  201. package/src/types/hre.ts +2 -0
  202. package/src/types/index.ts +2 -0
  203. package/src/types/network.ts +2 -0
  204. package/src/types/plugins.ts +1 -2
  205. package/src/types/providers.ts +2 -0
  206. package/src/types/solidity.ts +2 -0
  207. package/src/types/tasks.ts +2 -0
  208. package/src/types/test.ts +2 -0
  209. package/src/types/user-interruptions.ts +2 -0
  210. package/templates/hardhat-3/01-node-test-runner-viem/package.json +11 -11
  211. package/templates/hardhat-3/01-node-test-runner-viem/tsconfig.json +4 -7
  212. package/templates/hardhat-3/02-mocha-ethers/package.json +13 -13
  213. package/templates/hardhat-3/02-mocha-ethers/tsconfig.json +4 -7
  214. package/templates/hardhat-3/03-minimal/package.json +2 -2
  215. package/templates/hardhat-3/03-minimal/tsconfig.json +4 -7
@@ -1,6 +1,6 @@
1
1
  import type { Abi } from "../../../types/artifacts.js";
2
2
  import type { ChainType } from "../../../types/network.js";
3
- import type { SolidityTestConfig } from "../../../types/test.js";
3
+ import type { SolidityTestProfileConfig } from "../../../types/test.js";
4
4
  import type {
5
5
  SolidityTestRunnerConfigArgs,
6
6
  PathPermission,
@@ -19,6 +19,7 @@ import {
19
19
  opHardforkFromString,
20
20
  l1HardforkFromString,
21
21
  } from "@nomicfoundation/edr";
22
+ import { toBigInt } from "@nomicfoundation/hardhat-utils/bigint";
22
23
  import { hexStringToBytes } from "@nomicfoundation/hardhat-utils/hex";
23
24
 
24
25
  import { DEFAULT_VERBOSITY, OPTIMISM_CHAIN_TYPE } from "../../constants.js";
@@ -32,12 +33,13 @@ interface SolidityTestConfigParams {
32
33
  chainType: ChainType;
33
34
  projectRoot: string;
34
35
  hardfork?: string;
35
- config: SolidityTestConfig;
36
+ config: Omit<SolidityTestProfileConfig, "eip712Types">;
36
37
  verbosity: number;
37
38
  observability?: ObservabilityConfig;
38
39
  testPattern?: string;
39
40
  generateGasReport: boolean;
40
41
  testFunctionOverrides?: TestFunctionOverride[];
42
+ eip712CanonicalTypes?: string[];
41
43
  }
42
44
 
43
45
  export async function solidityTestConfigToSolidityTestRunnerConfigArgs({
@@ -50,6 +52,7 @@ export async function solidityTestConfigToSolidityTestRunnerConfigArgs({
50
52
  testPattern,
51
53
  generateGasReport,
52
54
  testFunctionOverrides,
55
+ eip712CanonicalTypes,
53
56
  }: SolidityTestConfigParams): Promise<SolidityTestRunnerConfigArgs> {
54
57
  const fsPermissions: PathPermission[] | undefined = [
55
58
  config.fsPermissions?.readWriteFile?.map((p) => ({
@@ -98,8 +101,18 @@ export async function solidityTestConfigToSolidityTestRunnerConfigArgs({
98
101
  const includeTraces = verbosityToIncludeTraces(verbosity);
99
102
 
100
103
  const blockGasLimit =
101
- config.blockGasLimit === false ? undefined : config.blockGasLimit;
102
- const disableBlockGasLimit = config.blockGasLimit === false;
104
+ typeof config.blockGasLimit === "number" ||
105
+ typeof config.blockGasLimit === "bigint"
106
+ ? toBigInt(config.blockGasLimit)
107
+ : undefined;
108
+ const disableBlockGasLimit = blockGasLimit === undefined;
109
+
110
+ const transactionGasCap =
111
+ typeof config.transactionGasCap === "number" ||
112
+ typeof config.transactionGasCap === "bigint"
113
+ ? toBigInt(config.transactionGasCap)
114
+ : undefined;
115
+ const disableTransactionGasCap = transactionGasCap === undefined;
103
116
 
104
117
  const blockDifficulty = config.prevRandao;
105
118
 
@@ -136,6 +149,8 @@ export async function solidityTestConfigToSolidityTestRunnerConfigArgs({
136
149
  includeTraces,
137
150
  blockGasLimit,
138
151
  disableBlockGasLimit,
152
+ transactionGasCap,
153
+ disableTransactionGasCap,
139
154
  blockDifficulty,
140
155
  ethRpcUrl,
141
156
  forkBlockNumber,
@@ -145,15 +160,24 @@ export async function solidityTestConfigToSolidityTestRunnerConfigArgs({
145
160
  ? CollectStackTraces.Always
146
161
  : CollectStackTraces.OnFailure,
147
162
  testFunctionOverrides,
163
+ eip712CanonicalTypes,
148
164
  };
149
165
  }
150
166
 
151
167
  export function isTestSuiteArtifact(artifact: Artifact): boolean {
168
+ const bytecode = artifact.contract.bytecode;
169
+
170
+ // Skip abstract contracts and interfaces i.e. those with no bytecode
171
+ if (bytecode === "" || bytecode === "0x" || bytecode === undefined) {
172
+ return false;
173
+ }
174
+
152
175
  const abi: Abi = JSON.parse(artifact.contract.abi);
153
176
  return abi.some(({ type, name }) => {
154
177
  if (type === "function" && typeof name === "string") {
155
178
  return name.startsWith("test") || name.startsWith("invariant");
156
179
  }
180
+
157
181
  return false;
158
182
  });
159
183
  }
@@ -35,6 +35,7 @@ import {
35
35
  buildEdrArtifactsWithMetadata,
36
36
  getBuildInfosAndOutputs,
37
37
  } from "./edr-artifacts.js";
38
+ import { collectEip712CanonicalTypes } from "./eip712/index.js";
38
39
  import {
39
40
  isTestSuiteArtifact,
40
41
  warnDeprecatedTestFail,
@@ -43,6 +44,7 @@ import {
43
44
  import { getTestFunctionOverrides } from "./inline-config/index.js";
44
45
  import { testReporter } from "./reporter.js";
45
46
  import { run } from "./runner.js";
47
+ import { DEFAULT_TEST_PROFILE } from "./test-profiles.js";
46
48
 
47
49
  interface TestActionArguments {
48
50
  testFiles: string[];
@@ -200,7 +202,9 @@ const runSolidityTests: NewTaskActionFunction<TestActionArguments> = async (
200
202
  let includesFailures = false;
201
203
  let includesErrors = false;
202
204
 
203
- const solidityTestConfig = hre.config.test.solidity;
205
+ const { eip712Types, ...solidityTestConfig } =
206
+ hre.config.test.solidity.profiles[DEFAULT_TEST_PROFILE];
207
+
204
208
  let observabilityConfig: ObservabilityConfig | undefined;
205
209
  if (hre.globalOptions.coverage) {
206
210
  const coverage = getCoverageManager(hre);
@@ -232,6 +236,12 @@ const runSolidityTests: NewTaskActionFunction<TestActionArguments> = async (
232
236
  allBuildInfosAndOutputs,
233
237
  );
234
238
 
239
+ const eip712CanonicalTypes = collectEip712CanonicalTypes(
240
+ allBuildInfosAndOutputs,
241
+ sourceNameToUserSourceName,
242
+ eip712Types,
243
+ );
244
+
235
245
  const testRunnerConfig =
236
246
  await solidityTestConfigToSolidityTestRunnerConfigArgs({
237
247
  chainType,
@@ -245,6 +255,7 @@ const runSolidityTests: NewTaskActionFunction<TestActionArguments> = async (
245
255
  hre.globalOptions.gasStats ||
246
256
  hre.globalOptions.gasStatsJson !== undefined,
247
257
  testFunctionOverrides,
258
+ eip712CanonicalTypes,
248
259
  });
249
260
  const tracingConfig: TracingConfigWithBuffers = {
250
261
  buildInfos: allBuildInfosAndOutputs.map(({ buildInfo, output }) => ({
@@ -0,0 +1 @@
1
+ export const DEFAULT_TEST_PROFILE = "default";
@@ -14,7 +14,28 @@ declare module "../../../types/config.js" {
14
14
  }
15
15
 
16
16
  declare module "../../../types/test.js" {
17
- export interface SolidityTestFuzzConfigBase {
17
+ export interface SolidityTestFsPermissionsUserConfig {
18
+ readWriteFile?: string[];
19
+ readFile?: string[];
20
+ writeFile?: string[];
21
+ dangerouslyReadWriteDirectory?: string[];
22
+ readDirectory?: string[];
23
+ dangerouslyWriteDirectory?: string[];
24
+ }
25
+
26
+ export interface SolidityTestInvariantUserConfig {
27
+ failurePersistDir?: string;
28
+ runs?: number;
29
+ depth?: number;
30
+ failOnRevert?: boolean;
31
+ callOverride?: boolean;
32
+ dictionaryWeight?: number;
33
+ includeStorage?: boolean;
34
+ includePushBytes?: boolean;
35
+ shrinkRunLimit?: number;
36
+ }
37
+
38
+ export interface SolidityTestFuzzUserConfig {
18
39
  failurePersistDir?: string;
19
40
  failurePersistFile?: string;
20
41
  runs?: number;
@@ -26,19 +47,14 @@ declare module "../../../types/test.js" {
26
47
  showLogs?: boolean;
27
48
  }
28
49
 
29
- export interface SolidityTestFuzzConfig extends SolidityTestFuzzConfigBase {
30
- seed: string;
50
+ export interface SolidityTestForkingUserConfig {
51
+ url?: SensitiveString;
52
+ blockNumber?: number | bigint;
53
+ rpcEndpoints?: Record<string, SensitiveString>;
31
54
  }
32
55
 
33
- export interface SolidityTestConfigBase {
34
- fsPermissions?: {
35
- readWriteFile?: string[];
36
- readFile?: string[];
37
- writeFile?: string[];
38
- dangerouslyReadWriteDirectory?: string[];
39
- readDirectory?: string[];
40
- dangerouslyWriteDirectory?: string[];
41
- };
56
+ export interface SolidityTestProfileUserConfig {
57
+ fsPermissions?: SolidityTestFsPermissionsUserConfig;
42
58
  isolate?: boolean;
43
59
  ffi?: boolean;
44
60
  allowInternalExpectRevert?: boolean;
@@ -50,46 +66,97 @@ declare module "../../../types/test.js" {
50
66
  blockTimestamp?: bigint;
51
67
  prevRandao?: bigint;
52
68
  gasLimit?: bigint;
53
- blockGasLimit?: bigint | false;
54
-
55
- fuzz?: SolidityTestFuzzConfigBase;
56
- invariant?: {
57
- failurePersistDir?: string;
58
- runs?: number;
59
- depth?: number;
60
- failOnRevert?: boolean;
61
- callOverride?: boolean;
62
- dictionaryWeight?: number;
63
- includeStorage?: boolean;
64
- includePushBytes?: boolean;
65
- shrinkRunLimit?: number;
69
+ blockGasLimit?: number | bigint | false;
70
+ transactionGasCap?: number | bigint | false;
71
+ fuzz?: SolidityTestFuzzUserConfig;
72
+ invariant?: SolidityTestInvariantUserConfig;
73
+ forking?: SolidityTestForkingUserConfig;
74
+ eip712Types?: {
75
+ include?: string[];
76
+ exclude?: string[];
66
77
  };
67
78
  }
68
79
 
69
- export interface SolidityTestForkingUserConfig {
70
- url?: SensitiveString;
71
- blockNumber?: number | bigint;
72
- rpcEndpoints?: Record<string, SensitiveString>;
80
+ export interface SolidityTestProfilesUserConfig {
81
+ profiles: Record<string, SolidityTestProfileUserConfig>;
73
82
  }
74
83
 
75
- export interface SolidityTestUserConfig extends SolidityTestConfigBase {
76
- forking?: SolidityTestForkingUserConfig;
77
- }
84
+ export type SolidityTestUserConfig =
85
+ | SolidityTestProfileUserConfig
86
+ | SolidityTestProfilesUserConfig;
78
87
 
79
88
  export interface HardhatTestUserConfig {
80
89
  solidity?: SolidityTestUserConfig;
81
90
  }
82
91
 
92
+ export interface SolidityTestFsPermissionsConfig {
93
+ readWriteFile?: string[];
94
+ readFile?: string[];
95
+ writeFile?: string[];
96
+ dangerouslyReadWriteDirectory?: string[];
97
+ readDirectory?: string[];
98
+ dangerouslyWriteDirectory?: string[];
99
+ }
100
+
101
+ export interface SolidityTestInvariantConfig {
102
+ failurePersistDir?: string;
103
+ runs?: number;
104
+ depth?: number;
105
+ failOnRevert?: boolean;
106
+ callOverride?: boolean;
107
+ dictionaryWeight?: number;
108
+ includeStorage?: boolean;
109
+ includePushBytes?: boolean;
110
+ shrinkRunLimit?: number;
111
+ }
112
+
113
+ export interface SolidityTestFuzzConfig {
114
+ failurePersistDir?: string;
115
+ failurePersistFile?: string;
116
+ runs?: number;
117
+ maxTestRejects?: number;
118
+ seed: string;
119
+ dictionaryWeight?: number;
120
+ includeStorage?: boolean;
121
+ includePushBytes?: boolean;
122
+ showLogs?: boolean;
123
+ }
124
+
83
125
  export interface SolidityTestForkingConfig {
84
126
  url?: ResolvedConfigurationVariable;
85
127
  blockNumber?: bigint;
86
128
  rpcEndpoints?: Record<string, ResolvedConfigurationVariable>;
87
129
  }
88
130
 
89
- export interface SolidityTestConfig extends SolidityTestConfigBase {
131
+ export interface SolidityTestProfileConfig {
132
+ rpcCachePath: string;
133
+ fsPermissions?: SolidityTestFsPermissionsConfig;
134
+ isolate?: boolean;
135
+ ffi?: boolean;
136
+ allowInternalExpectRevert?: boolean;
137
+ from?: string; // 0x-prefixed hex string
138
+ txOrigin?: string; // 0x-prefixed hex string
139
+ initialBalance?: bigint;
140
+ blockBaseFeePerGas?: bigint;
141
+ coinbase?: string; // 0x-prefixed hex string
142
+ blockTimestamp?: bigint;
143
+ prevRandao?: bigint;
144
+ gasLimit?: bigint;
145
+ blockGasLimit?: number | bigint | false;
146
+ transactionGasCap?: number | bigint | false;
90
147
  fuzz: SolidityTestFuzzConfig;
148
+ invariant?: SolidityTestInvariantConfig;
91
149
  forking?: SolidityTestForkingConfig;
150
+ eip712Types: {
151
+ include: string[];
152
+ exclude: string[];
153
+ };
92
154
  }
155
+
156
+ export interface SolidityTestConfig {
157
+ profiles: Record<string, SolidityTestProfileConfig>;
158
+ }
159
+
93
160
  export interface HardhatTestConfig {
94
161
  solidity: SolidityTestConfig;
95
162
  }
@@ -49,6 +49,10 @@ import {
49
49
  import { spawn } from "./subprocess.js";
50
50
  import { getTemplates } from "./template.js";
51
51
 
52
+ export interface NonInteractiveInitHardhat3Options {
53
+ template: string;
54
+ }
55
+
52
56
  export interface InitHardhatOptions {
53
57
  hardhatVersion?: "hardhat-2" | "hardhat-3";
54
58
  workspace?: string;
@@ -60,6 +64,61 @@ export interface InitHardhatOptions {
60
64
 
61
65
  const log = createDebug("hardhat:core:cli:init");
62
66
 
67
+ export async function initHardhat3NonInteractive(
68
+ options: NonInteractiveInitHardhat3Options,
69
+ ): Promise<void> {
70
+ const [template, projectTypeAnalyticsPromise] = await getTemplate(
71
+ "hardhat-3",
72
+ options.template,
73
+ true,
74
+ );
75
+
76
+ const workspace = process.cwd();
77
+
78
+ try {
79
+ const configFilePath = await findClosestHardhatConfig(workspace);
80
+
81
+ throw new HardhatError(
82
+ HardhatError.ERRORS.CORE.GENERAL.HARDHAT_PROJECT_ALREADY_CREATED,
83
+ {
84
+ hardhatProjectRootPath: configFilePath,
85
+ },
86
+ );
87
+ } catch (err) {
88
+ if (
89
+ !HardhatError.isHardhatError(
90
+ err,
91
+ HardhatError.ERRORS.CORE.GENERAL.NO_CONFIG_FILE_FOUND,
92
+ )
93
+ ) {
94
+ throw err;
95
+ }
96
+ }
97
+
98
+ await assertNoNonInteractiveClashes(workspace, template);
99
+
100
+ console.log("Initializing project...");
101
+
102
+ await validatePackageJson(workspace, template.packageJson, true);
103
+
104
+ await copyProjectFilesNonInteractive(workspace, template);
105
+
106
+ console.log("Installing dependencies...");
107
+
108
+ await Promise.all([
109
+ installProjectDependencies({
110
+ workspace,
111
+ template,
112
+ install: true,
113
+ update: true,
114
+ formatSuccessMessage: false,
115
+ }),
116
+ projectTypeAnalyticsPromise,
117
+ ]);
118
+
119
+ console.log("Project initialized");
120
+ }
121
+
63
122
  /**
64
123
  * initHardhat implements the project initialization wizard flow.
65
124
  *
@@ -126,7 +185,11 @@ export async function initHardhat(options?: InitHardhatOptions): Promise<void> {
126
185
  // Run them only if the user opts-in to it
127
186
  // Concurrently, await the analytics hit
128
187
  await Promise.all([
129
- installProjectDependencies(workspace, template, options?.install),
188
+ installProjectDependencies({
189
+ workspace,
190
+ template,
191
+ install: options?.install,
192
+ }),
130
193
  projectTypeAnalyticsPromise,
131
194
  ]);
132
195
 
@@ -270,12 +333,17 @@ export async function getWorkspace(workspace?: string): Promise<string> {
270
333
  *
271
334
  * NOTE: This function is exported for testing purposes
272
335
  *
336
+ * @param hardhatVersion The version of Hardhat whose templates should be considered.
273
337
  * @param template The name of the template to use for the project initialization.
338
+ * @param includeAvailableTemplatesInErrors When true, a missing template throws
339
+ * `TEMPLATE_NOT_FOUND_WITH_LIST_OF_OPTIONS` (which lists the available
340
+ * templates) instead of the bare `TEMPLATE_NOT_FOUND`.
274
341
  * @returns A tuple with two elements: the template and a promise with the analytics hit.
275
342
  */
276
343
  export async function getTemplate(
277
344
  hardhatVersion: "hardhat-2" | "hardhat-3",
278
345
  template?: string,
346
+ includeAvailableTemplatesInErrors = false,
279
347
  ): Promise<[Template, Promise<boolean>]> {
280
348
  const templates = await getTemplates(hardhatVersion);
281
349
 
@@ -299,9 +367,38 @@ export async function getTemplate(
299
367
  // we wait for the GA hit before throwing
300
368
  await projectTypeAnalyticsPromise;
301
369
 
302
- throw new HardhatError(HardhatError.ERRORS.CORE.GENERAL.TEMPLATE_NOT_FOUND, {
303
- template,
304
- });
370
+ if (!includeAvailableTemplatesInErrors) {
371
+ throw new HardhatError(
372
+ HardhatError.ERRORS.CORE.GENERAL.TEMPLATE_NOT_FOUND,
373
+ {
374
+ template,
375
+ },
376
+ );
377
+ }
378
+
379
+ const availableTemplates = templates.map((t) => ` - ${t.name}`).join("\n");
380
+ throw new HardhatError(
381
+ HardhatError.ERRORS.CORE.GENERAL.TEMPLATE_NOT_FOUND_WITH_LIST_OF_OPTIONS,
382
+ {
383
+ template,
384
+ availableTemplates,
385
+ },
386
+ );
387
+ }
388
+
389
+ /**
390
+ * Prints the list of available templates for the specified Hardhat version.
391
+ *
392
+ * @param hardhatVersion The version of Hardhat whose templates should be
393
+ * printed.
394
+ */
395
+ export async function printTemplatesList(
396
+ hardhatVersion: "hardhat-2" | "hardhat-3",
397
+ print: (message: string) => void = console.log,
398
+ ): Promise<void> {
399
+ const templates = await getTemplates(hardhatVersion);
400
+ const lines = templates.map((t) => ` - ${t.name}`).join("\n");
401
+ print(`Available templates:\n${lines}`);
305
402
  }
306
403
 
307
404
  /**
@@ -496,23 +593,100 @@ export async function copyProjectFiles(
496
593
  console.log(`✨ ${styleText("cyan", `Template files copied`)} ✨`);
497
594
  }
498
595
 
596
+ // NOTE: This function is exported for testing purposes
597
+ export async function assertNoNonInteractiveClashes(
598
+ workspace: string,
599
+ template: Template,
600
+ ): Promise<void> {
601
+ const clashes: string[] = [];
602
+
603
+ for (const relativeTemplatePath of template.files) {
604
+ const relativeWorkspacePath =
605
+ relativeTemplateToWorkspacePath(relativeTemplatePath);
606
+
607
+ if (
608
+ relativeWorkspacePath === "package.json" ||
609
+ relativeWorkspacePath === "README.md" ||
610
+ path.basename(relativeWorkspacePath) === ".gitignore"
611
+ ) {
612
+ continue;
613
+ }
614
+
615
+ if (await exists(path.join(workspace, relativeWorkspacePath))) {
616
+ clashes.push(relativeWorkspacePath);
617
+ }
618
+ }
619
+
620
+ if (clashes.length === 0) {
621
+ return;
622
+ }
623
+
624
+ throw new HardhatError(
625
+ HardhatError.ERRORS.CORE.GENERAL.NON_INTERACTIVE_INIT_WOULD_OVERWRITE_FILES,
626
+ {
627
+ files: clashes.map((f) => ` - ${f}`).join("\n"),
628
+ },
629
+ );
630
+ }
631
+
632
+ // NOTE: This function is exported for testing purposes
633
+ export async function copyProjectFilesNonInteractive(
634
+ workspace: string,
635
+ template: Template,
636
+ ): Promise<void> {
637
+ for (const relativeTemplatePath of template.files) {
638
+ const relativeWorkspacePath =
639
+ relativeTemplateToWorkspacePath(relativeTemplatePath);
640
+ let absoluteWorkspacePath = path.join(workspace, relativeWorkspacePath);
641
+
642
+ if (path.basename(relativeWorkspacePath) === ".gitignore") {
643
+ if (await exists(absoluteWorkspacePath)) {
644
+ continue;
645
+ }
646
+ } else if (
647
+ relativeWorkspacePath === "README.md" &&
648
+ (await exists(absoluteWorkspacePath))
649
+ ) {
650
+ absoluteWorkspacePath = path.join(workspace, "HARDHAT.md");
651
+ if (await exists(absoluteWorkspacePath)) {
652
+ continue;
653
+ }
654
+ }
655
+
656
+ await ensureDir(path.dirname(absoluteWorkspacePath));
657
+ await copy(
658
+ path.join(template.path, relativeTemplatePath),
659
+ absoluteWorkspacePath,
660
+ );
661
+ }
662
+ }
663
+
499
664
  /**
500
665
  * installProjectDependencies prints the commands to install the project dependencies
501
666
  * and runs them if the install option is true or if the user opts-in to it.
502
667
  *
503
668
  * NOTE: This function is exported for testing purposes
504
669
  *
505
- * @param workspace The path to the workspace to initialize the project in.
506
- * @param template The template to use for the project initialization.
507
- * @param install Whether to install the project dependencies.
508
- * @param update Whether to update the project dependencies.
670
+ * @param options The installation options.
671
+ * @param options.workspace The path to the workspace to initialize the project in.
672
+ * @param options.template The template to use for the project initialization.
673
+ * @param options.install Whether to install the project dependencies.
674
+ * @param options.update Whether to update the project dependencies.
675
+ * @param options.formatSuccessMessage Whether to format the success message or not.
509
676
  */
510
- export async function installProjectDependencies(
511
- workspace: string,
512
- template: Template,
513
- install?: boolean,
514
- update?: boolean,
515
- ): Promise<void> {
677
+ export async function installProjectDependencies({
678
+ workspace,
679
+ template,
680
+ install,
681
+ update,
682
+ formatSuccessMessage = true,
683
+ }: {
684
+ workspace: string;
685
+ template: Template;
686
+ install?: boolean;
687
+ update?: boolean;
688
+ formatSuccessMessage?: boolean;
689
+ }): Promise<void> {
516
690
  const pathToWorkspacePackageJson = path.join(workspace, "package.json");
517
691
 
518
692
  const workspacePkg: PackageJson = await readJsonFile(
@@ -587,7 +761,11 @@ export async function installProjectDependencies(
587
761
  );
588
762
  }
589
763
 
590
- console.log(`✨ ${styleText("cyan", `Dependencies installed`)} ✨`);
764
+ if (formatSuccessMessage) {
765
+ console.log(`✨ ${styleText("cyan", `Dependencies installed`)} ✨`);
766
+ } else {
767
+ console.log(`Dependencies installed`);
768
+ }
591
769
  }
592
770
  }
593
771
 
@@ -640,7 +818,11 @@ export async function installProjectDependencies(
640
818
  );
641
819
  }
642
820
 
643
- console.log(`✨ ${styleText("cyan", `Dependencies updated`)} ✨`);
821
+ if (formatSuccessMessage) {
822
+ console.log(`✨ ${styleText("cyan", `Dependencies updated`)} ✨`);
823
+ } else {
824
+ console.log("Dependencies updated");
825
+ }
644
826
  }
645
827
  }
646
828
  }
@@ -96,7 +96,70 @@ export async function main(
96
96
  }
97
97
 
98
98
  if (builtinGlobalOptions.init) {
99
- const { initHardhat } = await import("./init/init.js");
99
+ const { initHardhat, initHardhat3NonInteractive, printTemplatesList } =
100
+ await import("./init/init.js");
101
+
102
+ let templateName: string | undefined;
103
+ let listTemplates = false;
104
+
105
+ for (let i = 0; i < cliArguments.length; i++) {
106
+ if (usedCliArguments[i]) {
107
+ continue;
108
+ }
109
+
110
+ if (cliArguments[i] === "--templates") {
111
+ usedCliArguments[i] = true;
112
+ listTemplates = true;
113
+ }
114
+ }
115
+
116
+ for (let i = 0; i < cliArguments.length; i++) {
117
+ if (usedCliArguments[i]) {
118
+ continue;
119
+ }
120
+
121
+ if (cliArguments[i] === "--template") {
122
+ usedCliArguments[i] = true;
123
+
124
+ if (templateName !== undefined) {
125
+ throw new HardhatError(
126
+ HardhatError.ERRORS.CORE.ARGUMENTS.DUPLICATED_NAME,
127
+ { name: "--template" },
128
+ );
129
+ }
130
+
131
+ if (listTemplates) {
132
+ throw new HardhatError(
133
+ HardhatError.ERRORS.CORE.ARGUMENTS.CANNOT_COMBINE_TEMPLATE_AND_TEMPLATES,
134
+ );
135
+ }
136
+
137
+ if (
138
+ usedCliArguments[i + 1] === undefined ||
139
+ usedCliArguments[i + 1] === true ||
140
+ cliArguments[i + 1] === undefined ||
141
+ cliArguments[i + 1].startsWith("-")
142
+ ) {
143
+ throw new HardhatError(
144
+ HardhatError.ERRORS.CORE.ARGUMENTS.MISSING_VALUE_FOR_ARGUMENT,
145
+ { argument: "--template" },
146
+ );
147
+ }
148
+
149
+ templateName = cliArguments[i + 1];
150
+ i++;
151
+ usedCliArguments[i] = true;
152
+ }
153
+ }
154
+
155
+ if (listTemplates) {
156
+ return await printTemplatesList("hardhat-3", print);
157
+ }
158
+
159
+ if (templateName !== undefined) {
160
+ return await initHardhat3NonInteractive({ template: templateName });
161
+ }
162
+
100
163
  return await initHardhat();
101
164
  }
102
165
 
@@ -1,3 +1,5 @@
1
+ import "./builtin-plugin-type-extensions.js";
2
+
1
3
  /**
2
4
  * The possible types of a global or task option.
3
5
  */
@@ -1,6 +1,8 @@
1
1
  import type { SolidityBuildInfo } from "./solidity/solidity-artifacts.js";
2
2
  import type { NonNeverKeys } from "./utils.js";
3
3
 
4
+ import "./builtin-plugin-type-extensions.js";
5
+
4
6
  /**
5
7
  * A map of bare contract names and fully qualified contract names to their
6
8
  * artifacts that will be completed by Hardhat's build system using module