hardhat 3.8.0 → 3.9.1

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 +36 -0
  2. package/dist/src/config.d.ts.map +1 -1
  3. package/dist/src/config.js +6 -5
  4. package/dist/src/config.js.map +1 -1
  5. package/dist/src/hhu.d.ts +3 -0
  6. package/dist/src/hhu.d.ts.map +1 -0
  7. package/dist/src/hhu.js +14 -0
  8. package/dist/src/hhu.js.map +1 -0
  9. package/dist/src/internal/builtin-plugins/artifacts/hook-handlers/hre.d.ts.map +1 -1
  10. package/dist/src/internal/builtin-plugins/artifacts/hook-handlers/hre.js +4 -1
  11. package/dist/src/internal/builtin-plugins/artifacts/hook-handlers/hre.js.map +1 -1
  12. package/dist/src/internal/builtin-plugins/coverage/config.d.ts +6 -0
  13. package/dist/src/internal/builtin-plugins/coverage/config.d.ts.map +1 -0
  14. package/dist/src/internal/builtin-plugins/coverage/config.js +18 -0
  15. package/dist/src/internal/builtin-plugins/coverage/config.js.map +1 -0
  16. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/config.d.ts +4 -0
  17. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/config.d.ts.map +1 -0
  18. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/config.js +15 -0
  19. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/config.js.map +1 -0
  20. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/solidity.d.ts.map +1 -1
  21. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/solidity.js +10 -1
  22. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/solidity.js.map +1 -1
  23. package/dist/src/internal/builtin-plugins/coverage/index.d.ts.map +1 -1
  24. package/dist/src/internal/builtin-plugins/coverage/index.js +1 -0
  25. package/dist/src/internal/builtin-plugins/coverage/index.js.map +1 -1
  26. package/dist/src/internal/builtin-plugins/coverage/type-extensions.d.ts +20 -0
  27. package/dist/src/internal/builtin-plugins/coverage/type-extensions.d.ts.map +1 -1
  28. package/dist/src/internal/builtin-plugins/gas-analytics/function-gas-snapshots.d.ts +2 -2
  29. package/dist/src/internal/builtin-plugins/gas-analytics/function-gas-snapshots.d.ts.map +1 -1
  30. package/dist/src/internal/builtin-plugins/gas-analytics/function-gas-snapshots.js +21 -23
  31. package/dist/src/internal/builtin-plugins/gas-analytics/function-gas-snapshots.js.map +1 -1
  32. package/dist/src/internal/builtin-plugins/gas-analytics/snapshot-cheatcodes.d.ts +2 -2
  33. package/dist/src/internal/builtin-plugins/gas-analytics/snapshot-cheatcodes.d.ts.map +1 -1
  34. package/dist/src/internal/builtin-plugins/gas-analytics/snapshot-cheatcodes.js +21 -27
  35. package/dist/src/internal/builtin-plugins/gas-analytics/snapshot-cheatcodes.js.map +1 -1
  36. package/dist/src/internal/builtin-plugins/gas-analytics/tasks/solidity-test/task-action.d.ts +3 -1
  37. package/dist/src/internal/builtin-plugins/gas-analytics/tasks/solidity-test/task-action.d.ts.map +1 -1
  38. package/dist/src/internal/builtin-plugins/gas-analytics/tasks/solidity-test/task-action.js +18 -10
  39. package/dist/src/internal/builtin-plugins/gas-analytics/tasks/solidity-test/task-action.js.map +1 -1
  40. package/dist/src/internal/builtin-plugins/hhu/index.d.ts +4 -0
  41. package/dist/src/internal/builtin-plugins/hhu/index.d.ts.map +1 -0
  42. package/dist/src/internal/builtin-plugins/hhu/index.js +9 -0
  43. package/dist/src/internal/builtin-plugins/hhu/index.js.map +1 -0
  44. package/dist/src/internal/builtin-plugins/hhu/tasks/constants/index.d.ts +3 -0
  45. package/dist/src/internal/builtin-plugins/hhu/tasks/constants/index.d.ts.map +1 -0
  46. package/dist/src/internal/builtin-plugins/hhu/tasks/constants/index.js +8 -0
  47. package/dist/src/internal/builtin-plugins/hhu/tasks/constants/index.js.map +1 -0
  48. package/dist/src/internal/builtin-plugins/hhu/tasks/constants/zero-address.d.ts +4 -0
  49. package/dist/src/internal/builtin-plugins/hhu/tasks/constants/zero-address.d.ts.map +1 -0
  50. package/dist/src/internal/builtin-plugins/hhu/tasks/constants/zero-address.js +6 -0
  51. package/dist/src/internal/builtin-plugins/hhu/tasks/constants/zero-address.js.map +1 -0
  52. package/dist/src/internal/builtin-plugins/hhu/tasks/convert/index.d.ts +3 -0
  53. package/dist/src/internal/builtin-plugins/hhu/tasks/convert/index.d.ts.map +1 -0
  54. package/dist/src/internal/builtin-plugins/hhu/tasks/convert/index.js +27 -0
  55. package/dist/src/internal/builtin-plugins/hhu/tasks/convert/index.js.map +1 -0
  56. package/dist/src/internal/builtin-plugins/hhu/tasks/convert/pad.d.ts +10 -0
  57. package/dist/src/internal/builtin-plugins/hhu/tasks/convert/pad.d.ts.map +1 -0
  58. package/dist/src/internal/builtin-plugins/hhu/tasks/convert/pad.js +31 -0
  59. package/dist/src/internal/builtin-plugins/hhu/tasks/convert/pad.js.map +1 -0
  60. package/dist/src/internal/builtin-plugins/hhu/tasks/fetch/block-number.d.ts +4 -0
  61. package/dist/src/internal/builtin-plugins/hhu/tasks/fetch/block-number.d.ts.map +1 -0
  62. package/dist/src/internal/builtin-plugins/hhu/tasks/fetch/block-number.js +17 -0
  63. package/dist/src/internal/builtin-plugins/hhu/tasks/fetch/block-number.js.map +1 -0
  64. package/dist/src/internal/builtin-plugins/hhu/tasks/fetch/index.d.ts +3 -0
  65. package/dist/src/internal/builtin-plugins/hhu/tasks/fetch/index.d.ts.map +1 -0
  66. package/dist/src/internal/builtin-plugins/hhu/tasks/fetch/index.js +8 -0
  67. package/dist/src/internal/builtin-plugins/hhu/tasks/fetch/index.js.map +1 -0
  68. package/dist/src/internal/builtin-plugins/hhu/tasks/index.d.ts +11 -0
  69. package/dist/src/internal/builtin-plugins/hhu/tasks/index.d.ts.map +1 -0
  70. package/dist/src/internal/builtin-plugins/hhu/tasks/index.js +20 -0
  71. package/dist/src/internal/builtin-plugins/hhu/tasks/index.js.map +1 -0
  72. package/dist/src/internal/builtin-plugins/hhu/tasks/utils-task.d.ts +13 -0
  73. package/dist/src/internal/builtin-plugins/hhu/tasks/utils-task.d.ts.map +1 -0
  74. package/dist/src/internal/builtin-plugins/hhu/tasks/utils-task.js +17 -0
  75. package/dist/src/internal/builtin-plugins/hhu/tasks/utils-task.js.map +1 -0
  76. package/dist/src/internal/builtin-plugins/hhu/types.d.ts +45 -0
  77. package/dist/src/internal/builtin-plugins/hhu/types.d.ts.map +1 -0
  78. package/dist/src/internal/builtin-plugins/hhu/types.js +2 -0
  79. package/dist/src/internal/builtin-plugins/hhu/types.js.map +1 -0
  80. package/dist/src/internal/builtin-plugins/index.d.ts.map +1 -1
  81. package/dist/src/internal/builtin-plugins/index.js +5 -0
  82. package/dist/src/internal/builtin-plugins/index.js.map +1 -1
  83. package/dist/src/internal/builtin-plugins/network-manager/edr/genesis-state.d.ts +2 -1
  84. package/dist/src/internal/builtin-plugins/network-manager/edr/genesis-state.d.ts.map +1 -1
  85. package/dist/src/internal/builtin-plugins/network-manager/edr/genesis-state.js +13 -10
  86. package/dist/src/internal/builtin-plugins/network-manager/edr/genesis-state.js.map +1 -1
  87. package/dist/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-solidity-errors.d.ts +1 -0
  88. package/dist/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-solidity-errors.d.ts.map +1 -1
  89. package/dist/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-solidity-errors.js +17 -0
  90. package/dist/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-solidity-errors.js.map +1 -1
  91. package/dist/src/internal/builtin-plugins/network-manager/index.d.ts.map +1 -1
  92. package/dist/src/internal/builtin-plugins/network-manager/index.js +2 -10
  93. package/dist/src/internal/builtin-plugins/network-manager/index.js.map +1 -1
  94. package/dist/src/internal/builtin-plugins/network-manager/network-option.d.ts +9 -0
  95. package/dist/src/internal/builtin-plugins/network-manager/network-option.d.ts.map +1 -0
  96. package/dist/src/internal/builtin-plugins/network-manager/network-option.js +15 -0
  97. package/dist/src/internal/builtin-plugins/network-manager/network-option.js.map +1 -0
  98. package/dist/src/internal/builtin-plugins/network-manager/request-handlers/handlers/accounts/automatic-sender-handler.d.ts +4 -2
  99. package/dist/src/internal/builtin-plugins/network-manager/request-handlers/handlers/accounts/automatic-sender-handler.d.ts.map +1 -1
  100. package/dist/src/internal/builtin-plugins/network-manager/request-handlers/handlers/accounts/automatic-sender-handler.js +28 -6
  101. package/dist/src/internal/builtin-plugins/network-manager/request-handlers/handlers/accounts/automatic-sender-handler.js.map +1 -1
  102. package/dist/src/internal/builtin-plugins/network-manager/type-validation.d.ts.map +1 -1
  103. package/dist/src/internal/builtin-plugins/network-manager/type-validation.js +10 -1
  104. package/dist/src/internal/builtin-plugins/network-manager/type-validation.js.map +1 -1
  105. package/dist/src/internal/builtin-plugins/solidity/build-system/warning-suppression.d.ts.map +1 -1
  106. package/dist/src/internal/builtin-plugins/solidity/build-system/warning-suppression.js +3 -0
  107. package/dist/src/internal/builtin-plugins/solidity/build-system/warning-suppression.js.map +1 -1
  108. package/dist/src/internal/builtin-plugins/solidity/source-names.d.ts +12 -0
  109. package/dist/src/internal/builtin-plugins/solidity/source-names.d.ts.map +1 -0
  110. package/dist/src/internal/builtin-plugins/solidity/source-names.js +18 -0
  111. package/dist/src/internal/builtin-plugins/solidity/source-names.js.map +1 -0
  112. package/dist/src/internal/builtin-plugins/solidity-test/config.d.ts.map +1 -1
  113. package/dist/src/internal/builtin-plugins/solidity-test/config.js +1 -4
  114. package/dist/src/internal/builtin-plugins/solidity-test/config.js.map +1 -1
  115. package/dist/src/internal/builtin-plugins/solidity-test/eip712/index.d.ts.map +1 -1
  116. package/dist/src/internal/builtin-plugins/solidity-test/eip712/index.js +7 -12
  117. package/dist/src/internal/builtin-plugins/solidity-test/eip712/index.js.map +1 -1
  118. package/dist/src/internal/builtin-plugins/solidity-test/stack-trace-solidity-errors.d.ts.map +1 -1
  119. package/dist/src/internal/builtin-plugins/solidity-test/stack-trace-solidity-errors.js +3 -1
  120. package/dist/src/internal/builtin-plugins/solidity-test/stack-trace-solidity-errors.js.map +1 -1
  121. package/dist/src/internal/cli/help/get-global-help-string.d.ts +3 -1
  122. package/dist/src/internal/cli/help/get-global-help-string.d.ts.map +1 -1
  123. package/dist/src/internal/cli/help/get-global-help-string.js +3 -3
  124. package/dist/src/internal/cli/help/get-global-help-string.js.map +1 -1
  125. package/dist/src/internal/cli/help/get-help-string.d.ts +3 -1
  126. package/dist/src/internal/cli/help/get-help-string.d.ts.map +1 -1
  127. package/dist/src/internal/cli/help/get-help-string.js +4 -4
  128. package/dist/src/internal/cli/help/get-help-string.js.map +1 -1
  129. package/dist/src/internal/cli/help/utils.d.ts +3 -1
  130. package/dist/src/internal/cli/help/utils.d.ts.map +1 -1
  131. package/dist/src/internal/cli/help/utils.js +2 -2
  132. package/dist/src/internal/cli/help/utils.js.map +1 -1
  133. package/dist/src/internal/cli/hhu.d.ts +14 -0
  134. package/dist/src/internal/cli/hhu.d.ts.map +1 -0
  135. package/dist/src/internal/cli/hhu.js +184 -0
  136. package/dist/src/internal/cli/hhu.js.map +1 -0
  137. package/dist/src/internal/cli/main.d.ts +0 -25
  138. package/dist/src/internal/cli/main.d.ts.map +1 -1
  139. package/dist/src/internal/cli/main.js +23 -303
  140. package/dist/src/internal/cli/main.js.map +1 -1
  141. package/dist/src/internal/cli/parser.d.ts +25 -0
  142. package/dist/src/internal/cli/parser.d.ts.map +1 -0
  143. package/dist/src/internal/cli/parser.js +282 -0
  144. package/dist/src/internal/cli/parser.js.map +1 -0
  145. package/dist/src/internal/cli/telemetry/analytics/analytics.d.ts +1 -1
  146. package/dist/src/internal/cli/telemetry/analytics/analytics.d.ts.map +1 -1
  147. package/dist/src/internal/cli/telemetry/analytics/analytics.js +2 -1
  148. package/dist/src/internal/cli/telemetry/analytics/analytics.js.map +1 -1
  149. package/dist/src/internal/cli/telemetry/analytics/types.d.ts +1 -0
  150. package/dist/src/internal/cli/telemetry/analytics/types.d.ts.map +1 -1
  151. package/dist/src/internal/edr/context.d.ts.map +1 -1
  152. package/dist/src/internal/edr/context.js +25 -7
  153. package/dist/src/internal/edr/context.js.map +1 -1
  154. package/dist/src/internal/using-hardhat2-plugin-errors.d.ts +2 -2
  155. package/dist/src/internal/using-hardhat2-plugin-errors.d.ts.map +1 -1
  156. package/dist/src/internal/using-hardhat2-plugin-errors.js +7 -3
  157. package/dist/src/internal/using-hardhat2-plugin-errors.js.map +1 -1
  158. package/dist/src/internal/{builtin-plugins/solidity-test/eip712 → utils}/glob.d.ts +4 -0
  159. package/dist/src/internal/utils/glob.d.ts.map +1 -0
  160. package/dist/src/internal/{builtin-plugins/solidity-test/eip712 → utils}/glob.js +3 -3
  161. package/dist/src/internal/utils/glob.js.map +1 -0
  162. package/dist/src/plugins.d.ts.map +1 -1
  163. package/dist/src/plugins.js +3 -2
  164. package/dist/src/plugins.js.map +1 -1
  165. package/package.json +4 -4
  166. package/src/config.ts +17 -5
  167. package/src/hhu.ts +18 -0
  168. package/src/internal/builtin-plugins/artifacts/hook-handlers/hre.ts +11 -3
  169. package/src/internal/builtin-plugins/coverage/config.ts +28 -0
  170. package/src/internal/builtin-plugins/coverage/hook-handlers/config.ts +30 -0
  171. package/src/internal/builtin-plugins/coverage/hook-handlers/solidity.ts +15 -2
  172. package/src/internal/builtin-plugins/coverage/index.ts +1 -0
  173. package/src/internal/builtin-plugins/coverage/type-extensions.ts +24 -0
  174. package/src/internal/builtin-plugins/gas-analytics/function-gas-snapshots.ts +32 -32
  175. package/src/internal/builtin-plugins/gas-analytics/snapshot-cheatcodes.ts +32 -36
  176. package/src/internal/builtin-plugins/gas-analytics/tasks/solidity-test/task-action.ts +22 -9
  177. package/src/internal/builtin-plugins/hhu/index.ts +13 -0
  178. package/src/internal/builtin-plugins/hhu/tasks/constants/index.ts +18 -0
  179. package/src/internal/builtin-plugins/hhu/tasks/constants/zero-address.ts +9 -0
  180. package/src/internal/builtin-plugins/hhu/tasks/convert/index.ts +40 -0
  181. package/src/internal/builtin-plugins/hhu/tasks/convert/pad.ts +61 -0
  182. package/src/internal/builtin-plugins/hhu/tasks/fetch/block-number.ts +28 -0
  183. package/src/internal/builtin-plugins/hhu/tasks/fetch/index.ts +18 -0
  184. package/src/internal/builtin-plugins/hhu/tasks/index.ts +36 -0
  185. package/src/internal/builtin-plugins/hhu/tasks/utils-task.ts +29 -0
  186. package/src/internal/builtin-plugins/hhu/types.ts +57 -0
  187. package/src/internal/builtin-plugins/index.ts +6 -0
  188. package/src/internal/builtin-plugins/network-manager/edr/genesis-state.ts +22 -14
  189. package/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-solidity-errors.ts +33 -0
  190. package/src/internal/builtin-plugins/network-manager/index.ts +3 -10
  191. package/src/internal/builtin-plugins/network-manager/network-option.ts +17 -0
  192. package/src/internal/builtin-plugins/network-manager/request-handlers/handlers/accounts/automatic-sender-handler.ts +39 -9
  193. package/src/internal/builtin-plugins/network-manager/type-validation.ts +14 -1
  194. package/src/internal/builtin-plugins/solidity/build-system/warning-suppression.ts +3 -0
  195. package/src/internal/builtin-plugins/solidity/source-names.ts +19 -0
  196. package/src/internal/builtin-plugins/solidity-test/config.ts +1 -4
  197. package/src/internal/builtin-plugins/solidity-test/eip712/index.ts +8 -16
  198. package/src/internal/builtin-plugins/solidity-test/stack-trace-solidity-errors.ts +6 -1
  199. package/src/internal/cli/help/get-global-help-string.ts +3 -2
  200. package/src/internal/cli/help/get-help-string.ts +4 -3
  201. package/src/internal/cli/help/utils.ts +2 -1
  202. package/src/internal/cli/hhu.ts +298 -0
  203. package/src/internal/cli/main.ts +41 -495
  204. package/src/internal/cli/parser.ts +472 -0
  205. package/src/internal/cli/telemetry/analytics/analytics.ts +5 -1
  206. package/src/internal/cli/telemetry/analytics/types.ts +3 -0
  207. package/src/internal/edr/context.ts +39 -23
  208. package/src/internal/using-hardhat2-plugin-errors.ts +12 -3
  209. package/src/internal/{builtin-plugins/solidity-test/eip712 → utils}/glob.ts +3 -3
  210. package/src/plugins.ts +5 -2
  211. package/templates/hardhat-3/01-node-test-runner-viem/package.json +6 -6
  212. package/templates/hardhat-3/02-mocha-ethers/package.json +9 -9
  213. package/templates/hardhat-3/03-minimal/package.json +1 -1
  214. package/dist/src/internal/builtin-plugins/solidity-test/eip712/glob.d.ts.map +0 -1
  215. package/dist/src/internal/builtin-plugins/solidity-test/eip712/glob.js.map +0 -1
package/src/config.ts CHANGED
@@ -7,6 +7,9 @@ import type { HardhatUserConfig } from "./types/config.js";
7
7
 
8
8
  import { throwUsingHardhat2PluginError } from "./internal/using-hardhat2-plugin-errors.js";
9
9
 
10
+ const DEFINE_PLUGIN_MIGRATION_HINT =
11
+ "To migrate a plugin to Hardhat 3, export a plugin object with definePlugin from hardhat/plugins and register hook handlers in its hookHandlers field.";
12
+
10
13
  /**
11
14
  * Defines a Hardhat user config.
12
15
  *
@@ -42,33 +45,42 @@ export function defineConfig(config: HardhatUserConfig): HardhatUserConfig {
42
45
  * @deprecated This function is part of the Hardhat 2 plugin API.
43
46
  */
44
47
  export function extendConfig(..._args: any): any {
45
- throwUsingHardhat2PluginError();
48
+ throwUsingHardhat2PluginError("extendConfig", DEFINE_PLUGIN_MIGRATION_HINT);
46
49
  }
47
50
 
48
51
  /**
49
52
  * @deprecated This function is part of the Hardhat 2 plugin API.
50
53
  */
51
54
  export function extendEnvironment(..._args: any): any {
52
- throwUsingHardhat2PluginError();
55
+ throwUsingHardhat2PluginError(
56
+ "extendEnvironment",
57
+ DEFINE_PLUGIN_MIGRATION_HINT,
58
+ );
53
59
  }
54
60
 
55
61
  /**
56
62
  * @deprecated This function is part of the Hardhat 2 plugin API.
57
63
  */
58
64
  export function extendProvider(..._args: any): any {
59
- throwUsingHardhat2PluginError();
65
+ throwUsingHardhat2PluginError("extendProvider", DEFINE_PLUGIN_MIGRATION_HINT);
60
66
  }
61
67
 
62
68
  /**
63
69
  * @deprecated This function is part of the Hardhat 2 plugin API.
64
70
  */
65
71
  export function scope(..._args: any): any {
66
- throwUsingHardhat2PluginError();
72
+ throwUsingHardhat2PluginError(
73
+ "scope",
74
+ "To migrate tasks to Hardhat 3, define them with task or emptyTask from hardhat/config and include them in a plugin exported with definePlugin from hardhat/plugins.",
75
+ );
67
76
  }
68
77
 
69
78
  /**
70
79
  * @deprecated This function is part of the Hardhat 2 plugin API.
71
80
  */
72
81
  export function subtask(..._args: any): any {
73
- throwUsingHardhat2PluginError();
82
+ throwUsingHardhat2PluginError(
83
+ "subtask",
84
+ "To migrate subtasks to Hardhat 3, define them as nested tasks with task or emptyTask from hardhat/config and include them in a plugin exported with definePlugin from hardhat/plugins.",
85
+ );
74
86
  }
package/src/hhu.ts ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { exitIfNodeVersionNotSupported } from "./internal/cli/node-version.js";
4
+
5
+ // We enable the sourcemaps before loading main, so that everything except this
6
+ // small file is loaded with sourcemaps enabled.
7
+ process.setSourceMapsEnabled(true);
8
+
9
+ // We check the Node.js version before loading main, so that if there is some
10
+ // unsupported js syntax or Node API elsewhere, we get to exit with a clear
11
+ // error before crashing.
12
+ exitIfNodeVersionNotSupported();
13
+
14
+ // eslint-disable-next-line no-restricted-syntax -- Allow top-level await here
15
+ const { main } = await import("./internal/cli/hhu.js");
16
+
17
+ // eslint-disable-next-line no-restricted-syntax -- We do want TLA here
18
+ await main(process.argv.slice(2));
@@ -4,6 +4,11 @@ import type {
4
4
  StringWithArtifactContractNamesAutocompletion,
5
5
  } from "../../../../types/artifacts.js";
6
6
  import type { HardhatRuntimeEnvironmentHooks } from "../../../../types/hooks.js";
7
+ import type { ArtifactManagerImplementation as ArtifactManagerImplementationT } from "../artifact-manager.js";
8
+
9
+ let ArtifactManagerImplementation:
10
+ | typeof ArtifactManagerImplementationT
11
+ | undefined;
7
12
 
8
13
  class LazyArtifactManager implements ArtifactManager {
9
14
  readonly #artifactsPath: string;
@@ -85,10 +90,13 @@ class LazyArtifactManager implements ArtifactManager {
85
90
  }
86
91
 
87
92
  async #getArtifactManager(): Promise<ArtifactManager> {
88
- if (this.#artifactManager === undefined) {
89
- const { ArtifactManagerImplementation } = await import(
93
+ if (ArtifactManagerImplementation === undefined) {
94
+ ({ ArtifactManagerImplementation } = await import(
90
95
  "../artifact-manager.js"
91
- );
96
+ ));
97
+ }
98
+
99
+ if (this.#artifactManager === undefined) {
92
100
  this.#artifactManager = new ArtifactManagerImplementation(
93
101
  this.#artifactsPath,
94
102
  );
@@ -0,0 +1,28 @@
1
+ import type { HardhatUserConfig } from "../../../config.js";
2
+ import type { CoverageConfig } from "../../../types/config.js";
3
+ import type { HardhatUserConfigValidationError } from "../../../types/hooks.js";
4
+
5
+ import { validateUserConfigZodType } from "@nomicfoundation/hardhat-zod-utils";
6
+ import { z } from "zod";
7
+
8
+ const userConfigType = z.object({
9
+ coverage: z
10
+ .object({
11
+ skipFiles: z.array(z.string()).optional(),
12
+ })
13
+ .optional(),
14
+ });
15
+
16
+ export function validateCoverageUserConfig(
17
+ userConfig: unknown,
18
+ ): HardhatUserConfigValidationError[] {
19
+ return validateUserConfigZodType(userConfig, userConfigType);
20
+ }
21
+
22
+ export function resolveCoverageConfig(
23
+ userConfig: HardhatUserConfig,
24
+ ): CoverageConfig {
25
+ return {
26
+ skipFiles: userConfig.coverage?.skipFiles ?? [],
27
+ };
28
+ }
@@ -0,0 +1,30 @@
1
+ import type { ConfigHooks } from "../../../../types/hooks.js";
2
+
3
+ import {
4
+ resolveCoverageConfig,
5
+ validateCoverageUserConfig,
6
+ } from "../config.js";
7
+
8
+ export default async (): Promise<Partial<ConfigHooks>> => {
9
+ const handlers: Partial<ConfigHooks> = {
10
+ validateUserConfig: async (userConfig) =>
11
+ validateCoverageUserConfig(userConfig),
12
+ resolveUserConfig: async (
13
+ userConfig,
14
+ resolveConfigurationVariable,
15
+ next,
16
+ ) => {
17
+ const resolvedConfig = await next(
18
+ userConfig,
19
+ resolveConfigurationVariable,
20
+ );
21
+
22
+ return {
23
+ ...resolvedConfig,
24
+ coverage: resolveCoverageConfig(userConfig),
25
+ };
26
+ },
27
+ };
28
+
29
+ return handlers;
30
+ };
@@ -8,6 +8,8 @@ import { HardhatError } from "@nomicfoundation/hardhat-errors";
8
8
  import { createDebug } from "@nomicfoundation/hardhat-utils/debug";
9
9
  import { ensureError } from "@nomicfoundation/hardhat-utils/error";
10
10
 
11
+ import { matchesAnyGlob } from "../../../utils/glob.js";
12
+ import { toUserSourceName } from "../../solidity/source-names.js";
11
13
  import { getCoverageManager } from "../helpers/accessors.js";
12
14
  import { instrumentSolidityFileForCompilationJob } from "../instrumentation.js";
13
15
 
@@ -22,12 +24,23 @@ export default async (): Promise<Partial<SolidityHooks>> => ({
22
24
  solcVersion,
23
25
  next,
24
26
  ) => {
27
+ // This hook runs on every project file of every build. Coverage is the
28
+ // only reason to preprocess them, so when it is off we pass the file
29
+ // through untouched and keep the common path free of the work below.
30
+ if (!context.globalOptions.coverage) {
31
+ return await next(context, sourceName, fsPath, fileContent, solcVersion);
32
+ }
33
+
25
34
  // NOTE: We do not want to instrument the test project files as we don't
26
35
  // want to report coverage for them.
27
-
28
36
  const isTestSource = (await context.solidity.getScope(fsPath)) === "tests";
29
37
 
30
- if (context.globalOptions.coverage && !isTestSource) {
38
+ const isSkipped = matchesAnyGlob(
39
+ toUserSourceName(sourceName),
40
+ context.config.coverage.skipFiles,
41
+ );
42
+
43
+ if (!isTestSource && !isSkipped) {
31
44
  try {
32
45
  const { source, metadata } = instrumentSolidityFileForCompilationJob({
33
46
  compilationJobSolcVersion: solcVersion,
@@ -16,6 +16,7 @@ const hardhatPlugin: HardhatPlugin = definePlugin({
16
16
  ],
17
17
  hookHandlers: {
18
18
  clean: () => import("./hook-handlers/clean.js"),
19
+ config: () => import("./hook-handlers/config.js"),
19
20
  hre: () => import("./hook-handlers/hre.js"),
20
21
  solidity: () => import("./hook-handlers/solidity.js"),
21
22
  test: () => import("./hook-handlers/test.js"),
@@ -3,3 +3,27 @@ declare module "../../../types/global-options.js" {
3
3
  coverage: boolean;
4
4
  }
5
5
  }
6
+
7
+ declare module "../../../types/config.js" {
8
+ export interface CoverageUserConfig {
9
+ /**
10
+ * Globs of Solidity source files to exclude from coverage instrumentation.
11
+ * A project file whose project-relative source name matches any of these
12
+ * globs is not instrumented during a `--coverage` run, and so does not
13
+ * appear in coverage reports.
14
+ */
15
+ skipFiles?: string[];
16
+ }
17
+
18
+ export interface HardhatUserConfig {
19
+ coverage?: CoverageUserConfig;
20
+ }
21
+
22
+ export interface CoverageConfig {
23
+ skipFiles: string[];
24
+ }
25
+
26
+ export interface HardhatConfig {
27
+ coverage: CoverageConfig;
28
+ }
29
+ }
@@ -64,7 +64,7 @@ export interface FunctionGasSnapshotChange {
64
64
  export interface FunctionGasSnapshotCheckResult {
65
65
  passed: boolean;
66
66
  comparison: FunctionGasSnapshotComparison;
67
- written: boolean;
67
+ noBaseline: boolean;
68
68
  }
69
69
 
70
70
  export function getFunctionGasSnapshotsPath(basePath: string): string {
@@ -323,16 +323,17 @@ export async function checkFunctionGasSnapshots(
323
323
  previousFunctionGasSnapshots = await readFunctionGasSnapshots(basePath);
324
324
  } catch (error) {
325
325
  if (error instanceof FileNotFoundError) {
326
- await writeFunctionGasSnapshots(basePath, functionGasSnapshots);
327
-
326
+ // Running a check without a stored snapshot is a mistake: fail so it's
327
+ // caught, but only when this run actually produced something to check.
328
+ const noBaseline = functionGasSnapshots.length > 0;
328
329
  return {
329
- passed: true,
330
+ passed: !noBaseline,
330
331
  comparison: {
331
332
  added: [],
332
333
  removed: [],
333
334
  changed: [],
334
335
  },
335
- written: true,
336
+ noBaseline,
336
337
  };
337
338
  }
338
339
 
@@ -344,59 +345,54 @@ export async function checkFunctionGasSnapshots(
344
345
  functionGasSnapshots,
345
346
  );
346
347
 
347
- // Update snapshots when functions are added or removed (but not changed)
348
- const hasAddedOrRemoved =
349
- comparison.added.length > 0 || comparison.removed.length > 0;
350
- if (comparison.changed.length === 0 && hasAddedOrRemoved) {
351
- await writeFunctionGasSnapshots(basePath, functionGasSnapshots);
352
- }
353
-
354
348
  return {
355
349
  passed: comparison.changed.length === 0,
356
350
  comparison,
357
- written: hasAddedOrRemoved,
351
+ noBaseline: false,
358
352
  };
359
353
  }
360
354
 
361
355
  export function logFunctionGasSnapshotsSection(
362
356
  result: FunctionGasSnapshotCheckResult,
363
357
  logger: typeof console.log = console.log,
358
+ isFiltered = false,
364
359
  ): void {
365
- const { comparison, written } = result;
360
+ const { comparison, noBaseline } = result;
366
361
  const changedLength = comparison.changed.length;
367
- const addedLength = comparison.added.length;
368
- const removedLength = comparison.removed.length;
369
362
  const hasChanges = changedLength > 0;
363
+ // On a filtered run (--grep or specific files), added and missing snapshots
364
+ // are mostly artifacts of the filter rather than real differences, so we
365
+ // don't report them.
366
+ const addedLength = isFiltered ? 0 : comparison.added.length;
367
+ const removedLength = isFiltered ? 0 : comparison.removed.length;
370
368
  const hasAdded = addedLength > 0;
371
369
  const hasRemoved = removedLength > 0;
372
370
  const hasAnyDifferences = hasChanges || hasAdded || hasRemoved;
373
- const isFirstTimeWrite = written && !hasAnyDifferences;
374
371
 
375
372
  // Nothing to report
376
- if (!isFirstTimeWrite && !hasAnyDifferences) {
373
+ if (!noBaseline && !hasAnyDifferences) {
377
374
  return;
378
375
  }
379
376
 
380
- logger(
381
- formatSectionHeader("Function gas snapshots", {
382
- changedLength,
383
- addedLength,
384
- removedLength,
385
- }),
386
- );
387
-
388
- if (isFirstTimeWrite) {
389
- logger();
377
+ if (noBaseline) {
390
378
  logger(
391
379
  styleText(
392
- "green",
393
- " No existing snapshots found. Function gas snapshots written successfully",
380
+ "yellow",
381
+ "Function gas snapshots: no snapshot found. Run your tests with --snapshot to create one.",
394
382
  ),
395
383
  );
396
384
  logger();
397
385
  return;
398
386
  }
399
387
 
388
+ logger(
389
+ formatSectionHeader("Function gas snapshots", {
390
+ changedLength,
391
+ addedLength,
392
+ removedLength,
393
+ }),
394
+ );
395
+
400
396
  if (hasChanges) {
401
397
  logger();
402
398
  printFunctionGasSnapshotChanges(comparison.changed, logger);
@@ -404,7 +400,9 @@ export function logFunctionGasSnapshotsSection(
404
400
 
405
401
  if (hasAdded) {
406
402
  logger();
407
- logger(` Added ${comparison.added.length} function(s):`);
403
+ logger(
404
+ ` ${comparison.added.length} function(s) produced by this run are not in the snapshot:`,
405
+ );
408
406
  const addedLines = stringifyFunctionGasSnapshots(comparison.added).split(
409
407
  "\n",
410
408
  );
@@ -415,7 +413,9 @@ export function logFunctionGasSnapshotsSection(
415
413
 
416
414
  if (hasRemoved) {
417
415
  logger();
418
- logger(` Removed ${comparison.removed.length} function(s):`);
416
+ logger(
417
+ ` ${comparison.removed.length} stored function(s) were not produced by this run:`,
418
+ );
419
419
  const removedLines = stringifyFunctionGasSnapshots(
420
420
  comparison.removed,
421
421
  ).split("\n");
@@ -78,7 +78,7 @@ export interface SnapshotCheatcodesComparison {
78
78
  export interface SnapshotCheatcodesCheckResult {
79
79
  passed: boolean;
80
80
  comparison: SnapshotCheatcodesComparison;
81
- written: boolean;
81
+ noBaseline: boolean;
82
82
  renamedGroups: RenamedSnapshotGroup[];
83
83
  }
84
84
 
@@ -363,20 +363,17 @@ export async function checkSnapshotCheatcodes(
363
363
  previousSnapshotCheatcodes = await readSnapshotCheatcodes(basePath);
364
364
  } catch (error) {
365
365
  if (error instanceof FileNotFoundError) {
366
- // Only write if there are cheatcodes to save
367
- const written = snapshotCheatcodes.size > 0;
368
- if (written) {
369
- await writeSnapshotCheatcodes(basePath, snapshotCheatcodes);
370
- }
371
-
366
+ // Running a check without stored snapshots is a mistake: fail so it's
367
+ // caught, but only when this run actually produced something to check.
368
+ const noBaseline = snapshotCheatcodes.size > 0;
372
369
  return {
373
- passed: true,
370
+ passed: !noBaseline,
374
371
  comparison: {
375
372
  added: [],
376
373
  removed: [],
377
374
  changed: [],
378
375
  },
379
- written,
376
+ noBaseline,
380
377
  renamedGroups,
381
378
  };
382
379
  }
@@ -389,17 +386,10 @@ export async function checkSnapshotCheatcodes(
389
386
  snapshotCheatcodes,
390
387
  );
391
388
 
392
- // Update snapshots when functions are added or removed (but not changed)
393
- const hasAddedOrRemoved =
394
- comparison.added.length > 0 || comparison.removed.length > 0;
395
- if (comparison.changed.length === 0 && hasAddedOrRemoved) {
396
- await writeSnapshotCheatcodes(basePath, snapshotCheatcodes);
397
- }
398
-
399
389
  return {
400
390
  passed: comparison.changed.length === 0,
401
391
  comparison,
402
- written: hasAddedOrRemoved,
392
+ noBaseline: false,
403
393
  renamedGroups,
404
394
  };
405
395
  }
@@ -407,42 +397,44 @@ export async function checkSnapshotCheatcodes(
407
397
  export function logSnapshotCheatcodesSection(
408
398
  result: SnapshotCheatcodesCheckResult,
409
399
  logger: typeof console.log = console.log,
400
+ isFiltered = false,
410
401
  ): void {
411
- const { comparison, written } = result;
402
+ const { comparison, noBaseline } = result;
412
403
  const changedLength = comparison.changed.length;
413
- const addedLength = comparison.added.length;
414
- const removedLength = comparison.removed.length;
415
404
  const hasChanges = changedLength > 0;
405
+ // On a filtered run (--grep or specific files), added and missing snapshots
406
+ // are mostly artifacts of the filter rather than real differences, so we
407
+ // don't report them.
408
+ const addedLength = isFiltered ? 0 : comparison.added.length;
409
+ const removedLength = isFiltered ? 0 : comparison.removed.length;
416
410
  const hasAdded = addedLength > 0;
417
411
  const hasRemoved = removedLength > 0;
418
412
  const hasAnyDifferences = hasChanges || hasAdded || hasRemoved;
419
- const isFirstTimeWrite = written && !hasAnyDifferences;
420
413
 
421
414
  // Nothing to report
422
- if (!isFirstTimeWrite && !hasAnyDifferences) {
415
+ if (!noBaseline && !hasAnyDifferences) {
423
416
  return;
424
417
  }
425
418
 
426
- logger(
427
- formatSectionHeader("Snapshot cheatcodes", {
428
- changedLength,
429
- addedLength,
430
- removedLength,
431
- }),
432
- );
433
-
434
- if (isFirstTimeWrite) {
435
- logger();
419
+ if (noBaseline) {
436
420
  logger(
437
421
  styleText(
438
- "green",
439
- " No existing snapshots found. Snapshot cheatcodes written successfully",
422
+ "yellow",
423
+ "Snapshot cheatcodes: no snapshots found. Run your tests with --snapshot to create one.",
440
424
  ),
441
425
  );
442
426
  logger();
443
427
  return;
444
428
  }
445
429
 
430
+ logger(
431
+ formatSectionHeader("Snapshot cheatcodes", {
432
+ changedLength,
433
+ addedLength,
434
+ removedLength,
435
+ }),
436
+ );
437
+
446
438
  if (hasChanges) {
447
439
  logger();
448
440
  printSnapshotCheatcodeChanges(comparison.changed, logger);
@@ -450,7 +442,9 @@ export function logSnapshotCheatcodesSection(
450
442
 
451
443
  if (hasAdded) {
452
444
  logger();
453
- logger(` Added ${comparison.added.length} snapshot(s):`);
445
+ logger(
446
+ ` ${comparison.added.length} snapshot(s) produced by this run are not in the snapshot:`,
447
+ );
454
448
  const addedLines = stringifySnapshotCheatcodes(comparison.added).split(
455
449
  "\n",
456
450
  );
@@ -461,7 +455,9 @@ export function logSnapshotCheatcodesSection(
461
455
 
462
456
  if (hasRemoved) {
463
457
  logger();
464
- logger(` Removed ${comparison.removed.length} snapshot(s):`);
458
+ logger(
459
+ ` ${comparison.removed.length} stored snapshot(s) were not produced by this run:`,
460
+ );
465
461
  const removedLines = stringifySnapshotCheatcodes(comparison.removed).split(
466
462
  "\n",
467
463
  );
@@ -31,6 +31,9 @@ import {
31
31
  interface GasAnalyticsTestActionArguments {
32
32
  snapshot: boolean;
33
33
  snapshotCheck: boolean;
34
+ // Forwarded from the base `test solidity` task; used to detect scoped runs.
35
+ grep?: string;
36
+ testFiles?: string[];
34
37
  }
35
38
 
36
39
  export interface SnapshotResult {
@@ -74,7 +77,11 @@ const runSolidityTests: TaskOverrideActionFunction<
74
77
  rootPath,
75
78
  suiteResults,
76
79
  );
77
- logSnapshotCheckResult(snapshotCheckResult);
80
+ // On a scoped run, added/missing snapshots are expected, so don't report
81
+ // them (they'd be noise from the filter, not real differences).
82
+ const isFiltered =
83
+ args.grep !== undefined || (args.testFiles?.length ?? 0) > 0;
84
+ logSnapshotCheckResult(snapshotCheckResult, console.log, isFiltered);
78
85
  snapshotCheckPassed =
79
86
  snapshotCheckResult.functionGasSnapshotsCheck.passed &&
80
87
  snapshotCheckResult.snapshotCheatcodesCheck.passed;
@@ -141,6 +148,7 @@ export async function handleSnapshotCheck(
141
148
  export function logSnapshotCheckResult(
142
149
  { functionGasSnapshotsCheck, snapshotCheatcodesCheck }: SnapshotCheckResult,
143
150
  logger: typeof console.log = console.log,
151
+ isFiltered = false,
144
152
  ): void {
145
153
  logger(
146
154
  functionGasSnapshotsCheck.passed && snapshotCheatcodesCheck.passed
@@ -148,23 +156,28 @@ export function logSnapshotCheckResult(
148
156
  : styleText("red", "Snapshot check failed"),
149
157
  );
150
158
 
159
+ // On a filtered run, added/removed aren't reported, so they don't count
160
+ // towards a section having output (which drives the spacing below).
161
+ const showAddedRemoved = !isFiltered;
151
162
  const functionGasHasOutput =
152
- functionGasSnapshotsCheck.written ||
163
+ functionGasSnapshotsCheck.noBaseline ||
153
164
  functionGasSnapshotsCheck.comparison.changed.length > 0 ||
154
- functionGasSnapshotsCheck.comparison.added.length > 0 ||
155
- functionGasSnapshotsCheck.comparison.removed.length > 0;
165
+ (showAddedRemoved &&
166
+ (functionGasSnapshotsCheck.comparison.added.length > 0 ||
167
+ functionGasSnapshotsCheck.comparison.removed.length > 0));
156
168
  const snapshotCheatcodesHasOutput =
157
- snapshotCheatcodesCheck.written ||
169
+ snapshotCheatcodesCheck.noBaseline ||
158
170
  snapshotCheatcodesCheck.comparison.changed.length > 0 ||
159
- snapshotCheatcodesCheck.comparison.added.length > 0 ||
160
- snapshotCheatcodesCheck.comparison.removed.length > 0;
171
+ (showAddedRemoved &&
172
+ (snapshotCheatcodesCheck.comparison.added.length > 0 ||
173
+ snapshotCheatcodesCheck.comparison.removed.length > 0));
161
174
 
162
175
  // Add an extra newline if function gas snapshots have output
163
176
  if (functionGasHasOutput) {
164
177
  logger();
165
178
  }
166
179
 
167
- logFunctionGasSnapshotsSection(functionGasSnapshotsCheck, logger);
180
+ logFunctionGasSnapshotsSection(functionGasSnapshotsCheck, logger, isFiltered);
168
181
 
169
182
  // Add an extra newline if only snapshot cheatcodes have output
170
183
  // (logFunctionGasSnapshotsSection adds one if it has output)
@@ -172,7 +185,7 @@ export function logSnapshotCheckResult(
172
185
  logger();
173
186
  }
174
187
 
175
- logSnapshotCheatcodesSection(snapshotCheatcodesCheck, logger);
188
+ logSnapshotCheatcodesSection(snapshotCheatcodesCheck, logger, isFiltered);
176
189
 
177
190
  // Add an extra newline if only the rename warnings have output
178
191
  // (logSnapshotCheatcodesSection adds one if it has output)
@@ -0,0 +1,13 @@
1
+ import type { HardhatPlugin } from "../../../types/plugins.js";
2
+
3
+ import { definePlugin } from "../../../plugins.js";
4
+
5
+ import { generateTasks } from "./tasks/index.js";
6
+
7
+ const hardhatPlugin: HardhatPlugin = definePlugin({
8
+ id: "builtin:hhu",
9
+ tasks: generateTasks({ prefixWithUtils: true }),
10
+ npmPackage: "hardhat",
11
+ });
12
+
13
+ export default hardhatPlugin;
@@ -0,0 +1,18 @@
1
+ import type { UtilsTaskDefinition } from "../../types.js";
2
+
3
+ import { emptyTask, task } from "../../../../core/config.js";
4
+ import { buildUtilsTask } from "../utils-task.js";
5
+
6
+ export function constants(prefix: string[]): UtilsTaskDefinition[] {
7
+ const constantsTask = emptyTask(
8
+ [...prefix, "constants"],
9
+ "Commonly used Ethereum constants",
10
+ ).build();
11
+
12
+ const zeroAddressTask = buildUtilsTask(
13
+ task([...prefix, "constants", "zero-address"], "Print the zero address"),
14
+ async () => await import("./zero-address.js"),
15
+ );
16
+
17
+ return [constantsTask, zeroAddressTask];
18
+ }
@@ -0,0 +1,9 @@
1
+ import type { NewUtilsTaskActionFunction } from "../../types.js";
2
+
3
+ const zeroAddress = "0x0000000000000000000000000000000000000000";
4
+
5
+ const zeroAddressAction: NewUtilsTaskActionFunction = async () => {
6
+ console.log(zeroAddress);
7
+ };
8
+
9
+ export default zeroAddressAction;
@@ -0,0 +1,40 @@
1
+ import type { UtilsTaskDefinition } from "../../types.js";
2
+
3
+ import { ArgumentType } from "../../../../../types/arguments.js";
4
+ import { emptyTask, task } from "../../../../core/config.js";
5
+ import { buildUtilsTask } from "../utils-task.js";
6
+
7
+ export function convert(prefix: string[]): UtilsTaskDefinition[] {
8
+ const convertTask = emptyTask(
9
+ [...prefix, "convert"],
10
+ "Convert values between common Ethereum representations",
11
+ ).build();
12
+
13
+ const padTask = buildUtilsTask(
14
+ task(
15
+ [...prefix, "convert", "pad"],
16
+ "Pad a hex string to a given byte length",
17
+ )
18
+ .addPositionalArgument({
19
+ name: "value",
20
+ description: "The hex string to pad",
21
+ })
22
+ .addOption({
23
+ name: "length",
24
+ description: "The target length, in bytes",
25
+ type: ArgumentType.INT,
26
+ defaultValue: 32,
27
+ })
28
+ .addFlag({
29
+ name: "left",
30
+ description: "Pad to the left (default)",
31
+ })
32
+ .addFlag({
33
+ name: "right",
34
+ description: "Pad to the right",
35
+ }),
36
+ async () => await import("./pad.js"),
37
+ );
38
+
39
+ return [convertTask, padTask];
40
+ }