hardhat 2.17.0 → 2.17.2

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 (207) hide show
  1. package/builtin-tasks/compile.js +28 -4
  2. package/builtin-tasks/compile.js.map +1 -1
  3. package/builtin-tasks/flatten.js +131 -5
  4. package/builtin-tasks/flatten.js.map +1 -1
  5. package/builtin-tasks/task-names.d.ts +2 -0
  6. package/builtin-tasks/task-names.d.ts.map +1 -1
  7. package/builtin-tasks/task-names.js +4 -2
  8. package/builtin-tasks/task-names.js.map +1 -1
  9. package/builtin-tasks/utils/solidity-files-cache.js +3 -3
  10. package/builtin-tasks/utils/solidity-files-cache.js.map +1 -1
  11. package/builtin-tasks/utils/watch.d.ts +1 -1
  12. package/builtin-tasks/utils/watch.d.ts.map +1 -1
  13. package/console.sol +1192 -1171
  14. package/internal/artifacts.d.ts +28 -0
  15. package/internal/artifacts.d.ts.map +1 -1
  16. package/internal/artifacts.js +39 -1
  17. package/internal/artifacts.js.map +1 -1
  18. package/internal/cli/ArgumentsParser.js +1 -1
  19. package/internal/cli/ArgumentsParser.js.map +1 -1
  20. package/internal/cli/analytics.d.ts +1 -1
  21. package/internal/cli/analytics.d.ts.map +1 -1
  22. package/internal/cli/analytics.js +4 -5
  23. package/internal/cli/analytics.js.map +1 -1
  24. package/internal/cli/project-creation.js +1 -1
  25. package/internal/cli/types.d.ts +1 -1
  26. package/internal/cli/types.d.ts.map +1 -1
  27. package/internal/context.d.ts +1 -1
  28. package/internal/context.d.ts.map +1 -1
  29. package/internal/core/errors-list.d.ts +28 -0
  30. package/internal/core/errors-list.d.ts.map +1 -1
  31. package/internal/core/errors-list.js +34 -0
  32. package/internal/core/errors-list.js.map +1 -1
  33. package/internal/core/errors.js +17 -17
  34. package/internal/core/errors.js.map +1 -1
  35. package/internal/core/jsonrpc/types/access-list.d.ts +2 -2
  36. package/internal/core/jsonrpc/types/access-list.d.ts.map +1 -1
  37. package/internal/core/jsonrpc/types/base-types.d.ts +1 -0
  38. package/internal/core/jsonrpc/types/base-types.d.ts.map +1 -1
  39. package/internal/core/jsonrpc/types/base-types.js +8 -1
  40. package/internal/core/jsonrpc/types/base-types.js.map +1 -1
  41. package/internal/core/jsonrpc/types/input/blockTag.d.ts +4 -4
  42. package/internal/core/jsonrpc/types/input/blockTag.d.ts.map +1 -1
  43. package/internal/core/jsonrpc/types/input/callRequest.d.ts +61 -1
  44. package/internal/core/jsonrpc/types/input/callRequest.d.ts.map +1 -1
  45. package/internal/core/jsonrpc/types/input/callRequest.js +13 -1
  46. package/internal/core/jsonrpc/types/input/callRequest.js.map +1 -1
  47. package/internal/core/jsonrpc/types/input/debugTraceTransaction.d.ts +3 -1
  48. package/internal/core/jsonrpc/types/input/debugTraceTransaction.d.ts.map +1 -1
  49. package/internal/core/jsonrpc/types/input/debugTraceTransaction.js +1 -0
  50. package/internal/core/jsonrpc/types/input/debugTraceTransaction.js.map +1 -1
  51. package/internal/core/jsonrpc/types/input/filterRequest.d.ts +2 -2
  52. package/internal/core/jsonrpc/types/input/filterRequest.d.ts.map +1 -1
  53. package/internal/core/jsonrpc/types/input/hardhat-network.d.ts +3 -3
  54. package/internal/core/jsonrpc/types/input/hardhat-network.d.ts.map +1 -1
  55. package/internal/core/jsonrpc/types/input/logAddress.d.ts +2 -2
  56. package/internal/core/jsonrpc/types/input/logAddress.d.ts.map +1 -1
  57. package/internal/core/jsonrpc/types/input/logTopics.d.ts +2 -2
  58. package/internal/core/jsonrpc/types/input/logTopics.d.ts.map +1 -1
  59. package/internal/core/jsonrpc/types/input/solc.d.ts +2 -2
  60. package/internal/core/jsonrpc/types/input/solc.d.ts.map +1 -1
  61. package/internal/core/jsonrpc/types/input/subscribeRequest.d.ts +1 -1
  62. package/internal/core/jsonrpc/types/input/subscribeRequest.d.ts.map +1 -1
  63. package/internal/core/jsonrpc/types/input/transactionRequest.d.ts +1 -1
  64. package/internal/core/jsonrpc/types/input/transactionRequest.d.ts.map +1 -1
  65. package/internal/core/jsonrpc/types/output/block.d.ts +2 -2
  66. package/internal/core/jsonrpc/types/output/block.d.ts.map +1 -1
  67. package/internal/core/jsonrpc/types/output/log.d.ts +1 -1
  68. package/internal/core/jsonrpc/types/output/log.d.ts.map +1 -1
  69. package/internal/core/jsonrpc/types/output/receipt.d.ts +1 -1
  70. package/internal/core/jsonrpc/types/output/receipt.d.ts.map +1 -1
  71. package/internal/core/jsonrpc/types/output/transaction.d.ts +1 -1
  72. package/internal/core/jsonrpc/types/output/transaction.d.ts.map +1 -1
  73. package/internal/core/providers/construction.d.ts.map +1 -1
  74. package/internal/core/providers/construction.js +1 -0
  75. package/internal/core/providers/construction.js.map +1 -1
  76. package/internal/core/providers/errors.js +12 -12
  77. package/internal/core/providers/errors.js.map +1 -1
  78. package/internal/core/providers/gas-providers.js +1 -1
  79. package/internal/core/providers/gas-providers.js.map +1 -1
  80. package/internal/core/providers/http.d.ts.map +1 -1
  81. package/internal/core/providers/http.js +5 -3
  82. package/internal/core/providers/http.js.map +1 -1
  83. package/internal/core/providers/lazy-initialization.d.ts +2 -2
  84. package/internal/core/providers/lazy-initialization.d.ts.map +1 -1
  85. package/internal/core/runtime-environment.js +1 -1
  86. package/internal/core/runtime-environment.js.map +1 -1
  87. package/internal/core/tasks/task-definitions.js +3 -3
  88. package/internal/core/tasks/task-definitions.js.map +1 -1
  89. package/internal/hardhat-network/provider/PoolState.d.ts +4 -4
  90. package/internal/hardhat-network/provider/PoolState.d.ts.map +1 -1
  91. package/internal/hardhat-network/provider/fork/ForkBlockchain.d.ts.map +1 -1
  92. package/internal/hardhat-network/provider/fork/ForkBlockchain.js +13 -1
  93. package/internal/hardhat-network/provider/fork/ForkBlockchain.js.map +1 -1
  94. package/internal/hardhat-network/provider/fork/rpcToTxData.d.ts +6 -1
  95. package/internal/hardhat-network/provider/fork/rpcToTxData.d.ts.map +1 -1
  96. package/internal/hardhat-network/provider/fork/rpcToTxData.js.map +1 -1
  97. package/internal/hardhat-network/provider/modules/debug.d.ts +1 -0
  98. package/internal/hardhat-network/provider/modules/debug.d.ts.map +1 -1
  99. package/internal/hardhat-network/provider/modules/debug.js +8 -1
  100. package/internal/hardhat-network/provider/modules/debug.js.map +1 -1
  101. package/internal/hardhat-network/provider/modules/eth.d.ts.map +1 -1
  102. package/internal/hardhat-network/provider/modules/eth.js +3 -3
  103. package/internal/hardhat-network/provider/modules/eth.js.map +1 -1
  104. package/internal/hardhat-network/provider/node-types.d.ts +8 -7
  105. package/internal/hardhat-network/provider/node-types.d.ts.map +1 -1
  106. package/internal/hardhat-network/provider/node.d.ts +8 -1
  107. package/internal/hardhat-network/provider/node.d.ts.map +1 -1
  108. package/internal/hardhat-network/provider/node.js +126 -67
  109. package/internal/hardhat-network/provider/node.js.map +1 -1
  110. package/internal/hardhat-network/provider/output.d.ts +2 -2
  111. package/internal/hardhat-network/provider/output.d.ts.map +1 -1
  112. package/internal/hardhat-network/provider/provider.d.ts +1 -0
  113. package/internal/hardhat-network/provider/provider.d.ts.map +1 -1
  114. package/internal/hardhat-network/provider/provider.js +1 -0
  115. package/internal/hardhat-network/provider/provider.js.map +1 -1
  116. package/internal/hardhat-network/provider/transactions/FakeSenderAccessListEIP2930Transaction.js +11 -11
  117. package/internal/hardhat-network/provider/transactions/FakeSenderAccessListEIP2930Transaction.js.map +1 -1
  118. package/internal/hardhat-network/provider/transactions/FakeSenderEIP1559Transaction.js +10 -10
  119. package/internal/hardhat-network/provider/transactions/FakeSenderEIP1559Transaction.js.map +1 -1
  120. package/internal/hardhat-network/provider/transactions/FakeSenderTransaction.js +11 -11
  121. package/internal/hardhat-network/provider/transactions/FakeSenderTransaction.js.map +1 -1
  122. package/internal/hardhat-network/provider/transactions/ReadOnlyValidEIP1559Transaction.js +12 -12
  123. package/internal/hardhat-network/provider/transactions/ReadOnlyValidEIP1559Transaction.js.map +1 -1
  124. package/internal/hardhat-network/provider/transactions/ReadOnlyValidEIP2930Transaction.js +12 -12
  125. package/internal/hardhat-network/provider/transactions/ReadOnlyValidEIP2930Transaction.js.map +1 -1
  126. package/internal/hardhat-network/provider/transactions/ReadOnlyValidTransaction.js +5 -5
  127. package/internal/hardhat-network/provider/transactions/ReadOnlyValidTransaction.js.map +1 -1
  128. package/internal/hardhat-network/provider/transactions/ReadOnlyValidUnknownTypeTransaction.js +6 -6
  129. package/internal/hardhat-network/provider/transactions/ReadOnlyValidUnknownTypeTransaction.js.map +1 -1
  130. package/internal/hardhat-network/provider/utils/makeCommon.d.ts +1 -1
  131. package/internal/hardhat-network/provider/utils/makeCommon.d.ts.map +1 -1
  132. package/internal/hardhat-network/provider/utils/makeCommon.js +3 -1
  133. package/internal/hardhat-network/provider/utils/makeCommon.js.map +1 -1
  134. package/internal/hardhat-network/stack-traces/consoleLogger.d.ts +2 -2
  135. package/internal/hardhat-network/stack-traces/consoleLogger.d.ts.map +1 -1
  136. package/internal/hardhat-network/stack-traces/constants.d.ts +1 -1
  137. package/internal/hardhat-network/stack-traces/constants.js +1 -1
  138. package/internal/hardhat-network/stack-traces/contracts-identifier.js +5 -5
  139. package/internal/hardhat-network/stack-traces/contracts-identifier.js.map +1 -1
  140. package/internal/hardhat-network/stack-traces/message-trace.d.ts +4 -4
  141. package/internal/hardhat-network/stack-traces/message-trace.d.ts.map +1 -1
  142. package/internal/hardhat-network/stack-traces/model.js +5 -5
  143. package/internal/hardhat-network/stack-traces/model.js.map +1 -1
  144. package/internal/hardhat-network/stack-traces/solidity-stack-trace.d.ts +2 -2
  145. package/internal/hardhat-network/stack-traces/solidity-stack-trace.d.ts.map +1 -1
  146. package/internal/hardhat-network/stack-traces/vm-debug-tracer.d.ts.map +1 -1
  147. package/internal/hardhat-network/stack-traces/vm-debug-tracer.js +8 -8
  148. package/internal/hardhat-network/stack-traces/vm-debug-tracer.js.map +1 -1
  149. package/internal/sentry/reporter.js +12 -12
  150. package/internal/sentry/reporter.js.map +1 -1
  151. package/internal/solidity/compiler/downloader.js +11 -11
  152. package/internal/solidity/compiler/downloader.js.map +1 -1
  153. package/internal/solidity/dependencyGraph.d.ts.map +1 -1
  154. package/internal/solidity/dependencyGraph.js +17 -7
  155. package/internal/solidity/dependencyGraph.js.map +1 -1
  156. package/internal/solidity/resolver.d.ts +2 -1
  157. package/internal/solidity/resolver.d.ts.map +1 -1
  158. package/internal/solidity/resolver.js +31 -17
  159. package/internal/solidity/resolver.js.map +1 -1
  160. package/internal/util/jsonrpc.d.ts +1 -1
  161. package/internal/util/jsonrpc.d.ts.map +1 -1
  162. package/internal/util/unsafe.d.ts +1 -1
  163. package/internal/util/unsafe.d.ts.map +1 -1
  164. package/internal/util/unsafe.js.map +1 -1
  165. package/package.json +13 -16
  166. package/src/builtin-tasks/compile.ts +33 -4
  167. package/src/builtin-tasks/flatten.ts +228 -19
  168. package/src/builtin-tasks/task-names.ts +3 -0
  169. package/src/internal/artifacts.ts +40 -1
  170. package/src/internal/cli/analytics.ts +0 -3
  171. package/src/internal/cli/project-creation.ts +1 -1
  172. package/src/internal/core/errors-list.ts +38 -0
  173. package/src/internal/core/jsonrpc/types/base-types.ts +15 -0
  174. package/src/internal/core/jsonrpc/types/input/callRequest.ts +35 -1
  175. package/src/internal/core/jsonrpc/types/input/debugTraceTransaction.ts +1 -0
  176. package/src/internal/core/providers/construction.ts +2 -0
  177. package/src/internal/core/providers/http.ts +6 -3
  178. package/src/internal/hardhat-network/provider/fork/ForkBlockchain.ts +24 -4
  179. package/src/internal/hardhat-network/provider/fork/rpcToTxData.ts +10 -1
  180. package/src/internal/hardhat-network/provider/modules/debug.ts +21 -2
  181. package/src/internal/hardhat-network/provider/modules/eth.ts +18 -4
  182. package/src/internal/hardhat-network/provider/node-types.ts +1 -0
  183. package/src/internal/hardhat-network/provider/node.ts +110 -6
  184. package/src/internal/hardhat-network/provider/provider.ts +2 -0
  185. package/src/internal/hardhat-network/provider/utils/makeCommon.ts +9 -1
  186. package/src/internal/hardhat-network/stack-traces/constants.ts +1 -1
  187. package/src/internal/hardhat-network/stack-traces/vm-debug-tracer.ts +12 -10
  188. package/src/internal/solidity/dependencyGraph.ts +15 -3
  189. package/src/internal/solidity/resolver.ts +58 -16
  190. package/src/internal/util/unsafe.ts +1 -1
  191. package/src/types/config.ts +2 -0
  192. package/src/utils/contract-names.ts +1 -0
  193. package/src/utils/remappings.ts +17 -0
  194. package/types/config.d.ts +12 -10
  195. package/types/config.d.ts.map +1 -1
  196. package/types/experimental.d.ts +2 -2
  197. package/types/experimental.d.ts.map +1 -1
  198. package/types/runtime.d.ts +6 -6
  199. package/types/runtime.d.ts.map +1 -1
  200. package/utils/contract-names.d.ts +1 -0
  201. package/utils/contract-names.d.ts.map +1 -1
  202. package/utils/contract-names.js +1 -0
  203. package/utils/contract-names.js.map +1 -1
  204. package/utils/remappings.d.ts +2 -0
  205. package/utils/remappings.d.ts.map +1 -0
  206. package/utils/remappings.js +15 -0
  207. package/utils/remappings.js.map +1 -0
@@ -1,3 +1,4 @@
1
+ import chalk from "chalk";
1
2
  import { subtask, task, types } from "../internal/core/config/config-env";
2
3
  import { HardhatError } from "../internal/core/errors";
3
4
  import { ERRORS } from "../internal/core/errors-list";
@@ -13,8 +14,23 @@ import {
13
14
  TASK_FLATTEN,
14
15
  TASK_FLATTEN_GET_DEPENDENCY_GRAPH,
15
16
  TASK_FLATTEN_GET_FLATTENED_SOURCE,
17
+ TASK_FLATTEN_GET_FLATTENED_SOURCE_AND_METADATA,
16
18
  } from "./task-names";
17
19
 
20
+ interface FlattenMetadata {
21
+ filesWithoutLicenses: string[];
22
+ pragmaDirective: string;
23
+ filesWithoutPragmaDirectives: string[];
24
+ filesWithDifferentPragmaDirectives: string[];
25
+ }
26
+
27
+ // Match every group where a SPDX license is defined. The first captured group is the license.
28
+ const SPDX_LICENSES_REGEX =
29
+ /^(?:\/\/|\/\*)\s*SPDX-License-Identifier:\s*([a-zA-Z\d+.-]+).*/gm;
30
+ // Match every group where a pragma directive is defined. The first captured group is the pragma directive.
31
+ const PRAGMA_DIRECTIVES_REGEX =
32
+ /^(?: |\t)*(pragma\s*abicoder\s*v(1|2)|pragma\s*experimental\s*ABIEncoderV2)\s*;/gim;
33
+
18
34
  function getSortedFiles(dependenciesGraph: DependencyGraph) {
19
35
  const tsort = require("tsort");
20
36
  const graph = tsort();
@@ -71,34 +87,187 @@ function getFileWithoutImports(resolvedFile: ResolvedFile) {
71
87
  .trim();
72
88
  }
73
89
 
90
+ function getLicensesInfo(sortedFiles: ResolvedFile[]): [string[], string[]] {
91
+ const licenses: Set<string> = new Set();
92
+ const filesWithoutLicenses: Set<string> = new Set();
93
+
94
+ for (const file of sortedFiles) {
95
+ const matches = [...file.content.rawContent.matchAll(SPDX_LICENSES_REGEX)];
96
+
97
+ if (matches.length === 0) {
98
+ filesWithoutLicenses.add(file.sourceName);
99
+ continue;
100
+ }
101
+
102
+ for (const groups of matches) {
103
+ licenses.add(groups[1]);
104
+ }
105
+ }
106
+
107
+ // Sort alphabetically
108
+ return [Array.from(licenses).sort(), Array.from(filesWithoutLicenses).sort()];
109
+ }
110
+
111
+ function getLicensesHeader(licenses: string[]): string {
112
+ return licenses.length <= 0
113
+ ? ""
114
+ : `\n\n// SPDX-License-Identifier: ${licenses.join(" AND ")}`;
115
+ }
116
+
117
+ function removeUnnecessarySpaces(str: string): string {
118
+ return str.replace(/\s+/g, " ").trim();
119
+ }
120
+
121
+ function getPragmaAbicoderDirectiveInfo(
122
+ sortedFiles: ResolvedFile[]
123
+ ): [string, string[], string[]] {
124
+ let directive = "";
125
+ const directivesByImportance = [
126
+ "pragma abicoder v1",
127
+ "pragma experimental ABIEncoderV2",
128
+ "pragma abicoder v2",
129
+ ];
130
+ const filesWithoutPragmaDirectives: Set<string> = new Set();
131
+ const filesWithMostImportantDirective: Array<[string, string]> = []; // Every array element has the structure: [ fileName, fileMostImportantDirective ]
132
+
133
+ for (const file of sortedFiles) {
134
+ const matches = [
135
+ ...file.content.rawContent.matchAll(PRAGMA_DIRECTIVES_REGEX),
136
+ ];
137
+
138
+ if (matches.length === 0) {
139
+ filesWithoutPragmaDirectives.add(file.sourceName);
140
+ continue;
141
+ }
142
+
143
+ let fileMostImportantDirective = "";
144
+ for (const groups of matches) {
145
+ const normalizedPragma = removeUnnecessarySpaces(groups[1]);
146
+
147
+ // Update the most important pragma directive among all the files
148
+ if (
149
+ directivesByImportance.indexOf(normalizedPragma) >
150
+ directivesByImportance.indexOf(directive)
151
+ ) {
152
+ directive = normalizedPragma;
153
+ }
154
+
155
+ // Update the most important pragma directive for the current file
156
+ if (
157
+ directivesByImportance.indexOf(normalizedPragma) >
158
+ directivesByImportance.indexOf(fileMostImportantDirective)
159
+ ) {
160
+ fileMostImportantDirective = normalizedPragma;
161
+ }
162
+ }
163
+
164
+ // Add in the array the most important directive for the current file
165
+ filesWithMostImportantDirective.push([
166
+ file.sourceName,
167
+ fileMostImportantDirective,
168
+ ]);
169
+ }
170
+
171
+ // Add to the array the files that have a pragma directive which is not the same as the main one that
172
+ // is going to be used in the flatten file
173
+ const filesWithDifferentPragmaDirectives = filesWithMostImportantDirective
174
+ .filter(([, fileDirective]) => fileDirective !== directive)
175
+ .map(([fileName]) => fileName);
176
+
177
+ // Sort alphabetically
178
+ return [
179
+ directive,
180
+ Array.from(filesWithoutPragmaDirectives).sort(),
181
+ filesWithDifferentPragmaDirectives.sort(),
182
+ ];
183
+ }
184
+
185
+ function getPragmaAbicoderDirectiveHeader(pragmaDirective: string): string {
186
+ return pragmaDirective === "" ? "" : `\n\n${pragmaDirective};`;
187
+ }
188
+
189
+ function replaceLicenses(file: string): string {
190
+ return file.replaceAll(
191
+ SPDX_LICENSES_REGEX,
192
+ (...groups) => `// Original license: SPDX_License_Identifier: ${groups[1]}`
193
+ );
194
+ }
195
+
196
+ function replacePragmaAbicoderDirectives(file: string): string {
197
+ return file.replaceAll(PRAGMA_DIRECTIVES_REGEX, (...groups) => {
198
+ return `// Original pragma directive: ${removeUnnecessarySpaces(
199
+ groups[1]
200
+ )}`;
201
+ });
202
+ }
203
+
74
204
  subtask(
75
- TASK_FLATTEN_GET_FLATTENED_SOURCE,
76
- "Returns all contracts and their dependencies flattened"
205
+ TASK_FLATTEN_GET_FLATTENED_SOURCE_AND_METADATA,
206
+ "Returns all contracts and their dependencies flattened. Also return metadata about pragma directives and SPDX licenses"
77
207
  )
78
208
  .addOptionalParam("files", undefined, undefined, types.any)
79
- .setAction(async ({ files }: { files?: string[] }, { run }) => {
80
- const dependencyGraph: DependencyGraph = await run(
81
- TASK_FLATTEN_GET_DEPENDENCY_GRAPH,
82
- { files }
83
- );
209
+ .setAction(
210
+ async (
211
+ { files }: { files?: string[] },
212
+ { run }
213
+ ): Promise<[string, FlattenMetadata | null]> => {
214
+ const dependencyGraph: DependencyGraph = await run(
215
+ TASK_FLATTEN_GET_DEPENDENCY_GRAPH,
216
+ { files }
217
+ );
84
218
 
85
- let flattened = "";
219
+ let flattened = "";
86
220
 
87
- if (dependencyGraph.getResolvedFiles().length === 0) {
88
- return flattened;
89
- }
221
+ if (dependencyGraph.getResolvedFiles().length === 0) {
222
+ return [flattened, null];
223
+ }
224
+
225
+ const packageJson = await getPackageJson();
226
+ flattened += `// Sources flattened with hardhat v${packageJson.version} https://hardhat.org`;
227
+
228
+ const sortedFiles = getSortedFiles(dependencyGraph);
229
+
230
+ const [licenses, filesWithoutLicenses] = getLicensesInfo(sortedFiles);
231
+ const [
232
+ pragmaDirective,
233
+ filesWithoutPragmaDirectives,
234
+ filesWithDifferentPragmaDirectives,
235
+ ] = getPragmaAbicoderDirectiveInfo(sortedFiles);
90
236
 
91
- const packageJson = await getPackageJson();
92
- flattened += `// Sources flattened with hardhat v${packageJson.version} https://hardhat.org`;
237
+ flattened += getLicensesHeader(licenses);
238
+ flattened += getPragmaAbicoderDirectiveHeader(pragmaDirective);
93
239
 
94
- const sortedFiles = getSortedFiles(dependencyGraph);
240
+ for (const file of sortedFiles) {
241
+ let tmpFile = getFileWithoutImports(file);
242
+ tmpFile = replaceLicenses(tmpFile);
243
+ tmpFile = replacePragmaAbicoderDirectives(tmpFile);
95
244
 
96
- for (const file of sortedFiles) {
97
- flattened += `\n\n// File ${file.getVersionedName()}\n`;
98
- flattened += `\n${getFileWithoutImports(file)}\n`;
245
+ flattened += `\n\n// File ${file.getVersionedName()}\n`;
246
+ flattened += `\n${tmpFile}\n`;
247
+ }
248
+
249
+ return [
250
+ flattened.trim(),
251
+ {
252
+ filesWithoutLicenses,
253
+ pragmaDirective,
254
+ filesWithoutPragmaDirectives,
255
+ filesWithDifferentPragmaDirectives,
256
+ },
257
+ ];
99
258
  }
259
+ );
100
260
 
101
- return flattened.trim();
261
+ // The following task is kept for backwards-compatibility reasons
262
+ subtask(
263
+ TASK_FLATTEN_GET_FLATTENED_SOURCE,
264
+ "Returns all contracts and their dependencies flattened"
265
+ )
266
+ .addOptionalParam("files", undefined, undefined, types.any)
267
+ .setAction(async ({ files }: { files?: string[] }, { run }) => {
268
+ return (
269
+ await run(TASK_FLATTEN_GET_FLATTENED_SOURCE_AND_METADATA, { files })
270
+ )[0];
102
271
  });
103
272
 
104
273
  subtask(TASK_FLATTEN_GET_DEPENDENCY_GRAPH)
@@ -135,5 +304,45 @@ task(
135
304
  types.inputFile
136
305
  )
137
306
  .setAction(async ({ files }: { files: string[] | undefined }, { run }) => {
138
- console.log(await run(TASK_FLATTEN_GET_FLATTENED_SOURCE, { files }));
307
+ const [flattenedFile, metadata]: [string, FlattenMetadata | null] =
308
+ await run(TASK_FLATTEN_GET_FLATTENED_SOURCE_AND_METADATA, { files });
309
+
310
+ console.log(flattenedFile);
311
+
312
+ if (metadata === null) return;
313
+
314
+ if (metadata.filesWithoutLicenses.length > 0) {
315
+ console.warn(
316
+ chalk.yellow(
317
+ `\nThe following file(s) do NOT specify SPDX licenses: ${metadata.filesWithoutLicenses.join(
318
+ ", "
319
+ )}`
320
+ )
321
+ );
322
+ }
323
+
324
+ if (
325
+ metadata.pragmaDirective !== "" &&
326
+ metadata.filesWithoutPragmaDirectives.length > 0
327
+ ) {
328
+ console.warn(
329
+ chalk.yellow(
330
+ `\nPragma abicoder directives are defined in some files, but they are not defined in the following ones: ${metadata.filesWithoutPragmaDirectives.join(
331
+ ", "
332
+ )}`
333
+ )
334
+ );
335
+ }
336
+
337
+ if (metadata.filesWithDifferentPragmaDirectives.length > 0) {
338
+ console.warn(
339
+ chalk.yellow(
340
+ `\nThe flattened file is using the pragma abicoder directive '${
341
+ metadata.pragmaDirective
342
+ }' but these files have a different pragma abicoder directive: ${metadata.filesWithDifferentPragmaDirectives.join(
343
+ ", "
344
+ )}`
345
+ )
346
+ );
347
+ }
139
348
  });
@@ -14,6 +14,7 @@ export const TASK_COMPILE_SOLIDITY_GET_SOURCE_NAMES =
14
14
  export const TASK_COMPILE_SOLIDITY_READ_FILE = "compile:solidity:read-file";
15
15
  export const TASK_COMPILE_TRANSFORM_IMPORT_NAME =
16
16
  "compile:solidity:transform-import-name";
17
+ export const TASK_COMPILE_GET_REMAPPINGS = "compile:solidity:get-remappings";
17
18
  export const TASK_COMPILE_SOLIDITY_GET_DEPENDENCY_GRAPH =
18
19
  "compile:solidity:get-dependency-graph";
19
20
  export const TASK_COMPILE_SOLIDITY_GET_COMPILATION_JOBS =
@@ -68,6 +69,8 @@ export const TASK_CONSOLE = "console";
68
69
  export const TASK_FLATTEN = "flatten";
69
70
  export const TASK_FLATTEN_GET_FLATTENED_SOURCE =
70
71
  "flatten:get-flattened-sources";
72
+ export const TASK_FLATTEN_GET_FLATTENED_SOURCE_AND_METADATA =
73
+ "flatten:get-flattened-sources-and-metadata";
71
74
  export const TASK_FLATTEN_GET_DEPENDENCY_GRAPH = "flatten:get-dependency-graph";
72
75
 
73
76
  export const TASK_HELP = "help";
@@ -78,7 +78,18 @@ export class Artifacts implements IArtifacts {
78
78
  }
79
79
 
80
80
  public async artifactExists(name: string): Promise<boolean> {
81
- const artifactPath = await this._getArtifactPath(name);
81
+ let artifactPath;
82
+ try {
83
+ artifactPath = await this._getArtifactPath(name);
84
+ } catch (e) {
85
+ if (HardhatError.isHardhatError(e)) {
86
+ return false;
87
+ }
88
+
89
+ // eslint-disable-next-line @nomicfoundation/hardhat-internal-rules/only-hardhat-error
90
+ throw e;
91
+ }
92
+
82
93
  return fsExtra.pathExists(artifactPath);
83
94
  }
84
95
 
@@ -407,6 +418,7 @@ export class Artifacts implements IArtifacts {
407
418
 
408
419
  /**
409
420
  * Returns the absolute path to the given artifact
421
+ * @throws {HardhatError} If the name is not fully qualified.
410
422
  */
411
423
  public formArtifactPathFromFullyQualifiedName(
412
424
  fullyQualifiedName: string
@@ -490,6 +502,11 @@ export class Artifacts implements IArtifacts {
490
502
  * If the name is fully qualified, the path is computed from it. If not, an
491
503
  * artifact that matches the given name is searched in the existing artifacts.
492
504
  * If there is an ambiguity, an error is thrown.
505
+ *
506
+ * @throws {HardhatError} with descriptor:
507
+ * - {@link ERRORS.ARTIFACTS.WRONG_CASING} if the path case doesn't match the one in the filesystem.
508
+ * - {@link ERRORS.ARTIFACTS.MULTIPLE_FOUND} if there are multiple artifacts matching the given contract name.
509
+ * - {@link ERRORS.ARTIFACTS.NOT_FOUND} if the artifact is not found.
493
510
  */
494
511
  private async _getArtifactPath(name: string): Promise<string> {
495
512
  const cached = this._cache?.artifactNameToArtifactPathCache.get(name);
@@ -603,6 +620,16 @@ export class Artifacts implements IArtifacts {
603
620
  return path.join(this._artifactsPath, sourceName, `${contractName}.json`);
604
621
  }
605
622
 
623
+ /**
624
+ * Returns the absolute path to the artifact that corresponds to the given
625
+ * fully qualified name.
626
+ * @param fullyQualifiedName The fully qualified name of the contract.
627
+ * @returns The absolute path to the artifact.
628
+ * @throws {HardhatError} with descriptor:
629
+ * - {@link ERRORS.CONTRACT_NAMES.INVALID_FULLY_QUALIFIED_NAME} If the name is not fully qualified.
630
+ * - {@link ERRORS.ARTIFACTS.WRONG_CASING} If the path case doesn't match the one in the filesystem.
631
+ * - {@link ERRORS.ARTIFACTS.NOT_FOUND} If the artifact is not found.
632
+ */
606
633
  private async _getValidArtifactPathFromFullyQualifiedName(
607
634
  fullyQualifiedName: string
608
635
  ): Promise<string> {
@@ -666,6 +693,9 @@ Please replace "${contractName}" for the correct contract name wherever you are
666
693
  }
667
694
  }
668
695
 
696
+ /**
697
+ * @throws {HardhatError} with a list of similar contract names.
698
+ */
669
699
  private _handleWrongArtifactForFullyQualifiedName(
670
700
  fullyQualifiedName: string
671
701
  ): never {
@@ -682,6 +712,9 @@ Please replace "${contractName}" for the correct contract name wherever you are
682
712
  });
683
713
  }
684
714
 
715
+ /**
716
+ * @throws {HardhatError} with a list of similar contract names.
717
+ */
685
718
  private _handleWrongArtifactForContractName(
686
719
  contractName: string,
687
720
  files: string[]
@@ -813,6 +846,12 @@ Please replace "${contractName}" for the correct contract name wherever you are
813
846
  return artifactPath.replace(/\.json$/, ".dbg.json");
814
847
  }
815
848
 
849
+ /**
850
+ * Gets the path to the artifact file for the given contract name.
851
+ * @throws {HardhatError} with descriptor:
852
+ * - {@link ERRORS.ARTIFACTS.NOT_FOUND} if there are no artifacts matching the given contract name.
853
+ * - {@link ERRORS.ARTIFACTS.MULTIPLE_FOUND} if there are multiple artifacts matching the given contract name.
854
+ */
816
855
  private _getArtifactPathFromFiles(
817
856
  contractName: string,
818
857
  files: string[]
@@ -1,4 +1,3 @@
1
- import type AbortControllerT from "abort-controller";
2
1
  import type { request as RequestT } from "undici";
3
2
 
4
3
  import debug from "debug";
@@ -128,8 +127,6 @@ export class Analytics {
128
127
 
129
128
  private _sendHit(payload: AnalyticsPayload): [AbortAnalytics, Promise<void>] {
130
129
  const { request } = require("undici") as { request: typeof RequestT };
131
- const AbortController =
132
- require("abort-controller") as typeof AbortControllerT;
133
130
 
134
131
  const eventName = payload.events[0].name;
135
132
  log(`Sending hit for ${eventName}`);
@@ -315,7 +315,7 @@ async function createPackageJson() {
315
315
  function showStarOnGitHubMessage() {
316
316
  console.log(
317
317
  chalk.cyan("Give Hardhat a star on Github if you're enjoying it!") +
318
- emoji(" 💞✨")
318
+ emoji(" ⭐️✨")
319
319
  );
320
320
  console.log();
321
321
  console.log(chalk.cyan(" https://github.com/NomicFoundation/hardhat"));
@@ -278,6 +278,16 @@ Rename the file to use the .cjs to fix this problem.`,
278
278
  To initialize the provider, make sure you first call \`.init()\` or any method that hits a node like request, send or sendAsync.`,
279
279
  shouldBeReported: true,
280
280
  },
281
+ INVALID_READ_OF_DIRECTORY: {
282
+ number: 22,
283
+ message:
284
+ "Invalid file path %absolutePath%. Attempting to read a directory instead of a file.",
285
+ title: "Invalid read: a directory cannot be read",
286
+ description: `An attempt was made to read a file, but a path to a directory was provided.
287
+
288
+ Please double check the file path.`,
289
+ shouldBeReported: false,
290
+ },
281
291
  },
282
292
  NETWORK: {
283
293
  CONFIG_NOT_FOUND: {
@@ -585,6 +595,14 @@ Please double check your task definitions.`,
585
595
  What makes these types special is that they can be represented as strings, so you can write them down in the terminal.`,
586
596
  shouldBeReported: false,
587
597
  },
598
+ DEPRECATED_TRANSFORM_IMPORT_TASK: {
599
+ number: 213,
600
+ title: "Use of deprecated remapping task",
601
+ message:
602
+ "Task TASK_COMPILE_TRANSFORM_IMPORT_NAME is deprecated. Please update your @nomicfoundation/hardhat-foundry plugin version.",
603
+ description: `This task has been deprecated in favor of a new approach.`,
604
+ shouldBeReported: true,
605
+ },
588
606
  },
589
607
  ARGUMENTS: {
590
608
  INVALID_ENV_VAR_VALUE: {
@@ -855,6 +873,26 @@ Use a relative import instead of referencing the package's name.`,
855
873
  Please double check your imports and installed libraries.`,
856
874
  shouldBeReported: false,
857
875
  },
876
+ INVALID_IMPORT_OF_DIRECTORY: {
877
+ number: 414,
878
+ message:
879
+ "Invalid import %imported% from %from%. Attempting to import a directory. Directories cannot be imported.",
880
+ title: "Invalid import: a directory cannot be imported",
881
+ description: `A Solidity file is attempting to import a directory, which is not possible.
882
+
883
+ Please double check your imports.`,
884
+ shouldBeReported: false,
885
+ },
886
+ AMBIGUOUS_SOURCE_NAMES: {
887
+ number: 415,
888
+ message:
889
+ "Two different source names (%sourcenames%) resolve to the same file (%file%).",
890
+ title: "Ambiguous source names",
891
+ description: `Two different source names map to the same file.
892
+
893
+ This is probably caused by multiple remappings pointing to the same source file.`,
894
+ shouldBeReported: false,
895
+ },
858
896
  },
859
897
  SOLC: {
860
898
  INVALID_VERSION: {
@@ -40,6 +40,17 @@ export const rpcStorageSlot = new t.Type<bigint>(
40
40
  t.identity
41
41
  );
42
42
 
43
+ // This type is necessary because objects' keys need to be either strings or numbers to be properly handled by the 'io-ts' module.
44
+ // If they are not defined as strings or numbers, the type definition will result in an empty object without the required properties.
45
+ // For example, instead of displaying { ke1: value1 }, it will display {}
46
+ export const rpcStorageSlotHexString = new t.Type<string>(
47
+ "Storage slot hex string",
48
+ (x): x is string => typeof x === "string",
49
+ (u, c) =>
50
+ validateRpcStorageSlotHexString(u) ? t.success(u) : t.failure(u, c),
51
+ t.identity
52
+ );
53
+
43
54
  function validateStorageSlot(u: unknown, c: t.Context): t.Validation<bigint> {
44
55
  if (typeof u !== "string") {
45
56
  return t.failure(
@@ -185,6 +196,10 @@ export function rpcDataToBuffer(data: string): Buffer {
185
196
 
186
197
  // Type guards
187
198
 
199
+ function validateRpcStorageSlotHexString(u: unknown): u is string {
200
+ return typeof u === "string" && /^0x([0-9a-fA-F]){64}$/.test(u);
201
+ }
202
+
188
203
  function isRpcQuantityString(u: unknown): u is string {
189
204
  return (
190
205
  typeof u === "string" &&
@@ -2,7 +2,14 @@ import * as t from "io-ts";
2
2
 
3
3
  import { optionalOrNullable } from "../../../../util/io-ts";
4
4
  import { rpcAccessList } from "../access-list";
5
- import { rpcAddress, rpcData, rpcQuantity } from "../base-types";
5
+ import {
6
+ rpcAddress,
7
+ rpcData,
8
+ rpcQuantity,
9
+ rpcStorageSlot,
10
+ rpcStorageSlotHexString,
11
+ } from "../base-types";
12
+ import { address } from "../../../config/config-validation";
6
13
 
7
14
  // Type used by eth_call and eth_estimateGas
8
15
  export const rpcCallRequest = t.type(
@@ -21,3 +28,30 @@ export const rpcCallRequest = t.type(
21
28
  );
22
29
 
23
30
  export type RpcCallRequest = t.TypeOf<typeof rpcCallRequest>;
31
+
32
+ // Types used by eth_call to configure the state override set
33
+ export const stateProperties = t.record(
34
+ rpcStorageSlotHexString,
35
+ rpcStorageSlot
36
+ );
37
+
38
+ export const stateOverrideOptions = t.type(
39
+ {
40
+ balance: optionalOrNullable(rpcQuantity),
41
+ nonce: optionalOrNullable(rpcQuantity),
42
+ code: optionalOrNullable(rpcData),
43
+ state: optionalOrNullable(stateProperties),
44
+ stateDiff: optionalOrNullable(stateProperties),
45
+ },
46
+ "stateOverrideOptions"
47
+ );
48
+
49
+ export const stateOverrideSet = t.record(address, stateOverrideOptions);
50
+ export const optionalStateOverrideSet = optionalOrNullable(stateOverrideSet);
51
+
52
+ export type StateProperties = t.TypeOf<typeof stateProperties>;
53
+ export type StateOverrideOptions = t.TypeOf<typeof stateOverrideOptions>;
54
+ export type StateOverrideSet = t.TypeOf<typeof stateOverrideSet>;
55
+ export type OptionalStateOverrideSet = t.TypeOf<
56
+ typeof optionalStateOverrideSet
57
+ >;
@@ -5,6 +5,7 @@ import { optionalOrNullable } from "../../../../util/io-ts";
5
5
  export const rpcDebugTracingConfig = optionalOrNullable(
6
6
  t.type(
7
7
  {
8
+ tracer: optionalOrNullable(t.string),
8
9
  disableStorage: optionalOrNullable(t.boolean),
9
10
  disableMemory: optionalOrNullable(t.boolean),
10
11
  disableStack: optionalOrNullable(t.boolean),
@@ -116,6 +116,8 @@ export async function createProvider(
116
116
  forkConfig,
117
117
  forkCachePath:
118
118
  paths !== undefined ? getForkCacheDirPath(paths) : undefined,
119
+ enableTransientStorage:
120
+ hardhatNetConfig.enableTransientStorage ?? false,
119
121
  },
120
122
  new ModulesLogger(hardhatNetConfig.loggingEnabled),
121
123
  artifacts
@@ -203,7 +203,7 @@ export class HttpProvider extends EventEmitter implements EIP1193Provider {
203
203
  // https://undici.nodejs.org/#/?id=garbage-collection
204
204
  // It's not clear how to "cancel", so we'll just consume:
205
205
  await response.body.text();
206
- const seconds = this._getRetryAfterSeconds(response);
206
+ const seconds = this._getRetryAfterSeconds(response, retryNumber);
207
207
  if (seconds !== undefined && this._shouldRetry(retryNumber, seconds)) {
208
208
  return await this._retry(request, seconds, retryNumber);
209
209
  }
@@ -272,12 +272,15 @@ export class HttpProvider extends EventEmitter implements EIP1193Provider {
272
272
  }
273
273
 
274
274
  private _getRetryAfterSeconds(
275
- response: Undici.Dispatcher.ResponseData
275
+ response: Undici.Dispatcher.ResponseData,
276
+ retryNumber: number
276
277
  ): number | undefined {
277
278
  const header = response.headers["retry-after"];
278
279
 
279
280
  if (header === undefined || header === null || Array.isArray(header)) {
280
- return undefined;
281
+ // if the response doesn't have a retry-after header, we do
282
+ // an exponential backoff
283
+ return Math.min(2 ** retryNumber, MAX_RETRY_AWAIT_SECONDS);
281
284
  }
282
285
 
283
286
  const parsed = parseInt(header, 10);
@@ -348,10 +348,30 @@ export class ForkBlockchain
348
348
  return undefined;
349
349
  }
350
350
 
351
- const transaction = new ReadOnlyValidTransaction(
352
- new Address(rpcTransaction.from),
353
- rpcToTxData(rpcTransaction)
354
- );
351
+ let transaction: TypedTransaction;
352
+
353
+ if (rpcTransaction.type === undefined || rpcTransaction.type === 0n) {
354
+ transaction = new ReadOnlyValidTransaction(
355
+ new Address(rpcTransaction.from),
356
+ rpcToTxData(rpcTransaction)
357
+ );
358
+ } else if (rpcTransaction.type === 1n) {
359
+ transaction = new ReadOnlyValidEIP2930Transaction(
360
+ new Address(rpcTransaction.from),
361
+ rpcToTxData(rpcTransaction)
362
+ );
363
+ } else if (rpcTransaction.type === 2n) {
364
+ transaction = new ReadOnlyValidEIP1559Transaction(
365
+ new Address(rpcTransaction.from),
366
+ rpcToTxData(rpcTransaction) as FeeMarketEIP1559TxData
367
+ );
368
+ } else {
369
+ transaction = new ReadOnlyValidUnknownTypeTransaction(
370
+ new Address(rpcTransaction.from),
371
+ Number(rpcTransaction.type),
372
+ rpcToTxData(rpcTransaction)
373
+ );
374
+ }
355
375
 
356
376
  this._data.addTransaction(transaction);
357
377
 
@@ -1,11 +1,20 @@
1
+ import type { BigIntLike } from "@nomicfoundation/ethereumjs-util";
2
+
1
3
  import {
2
4
  AccessListEIP2930TxData,
3
5
  TxData,
4
6
  } from "@nomicfoundation/ethereumjs-tx";
5
7
 
6
- import { FeeMarketEIP1559TxData } from "@nomicfoundation/ethereumjs-tx/dist/types";
7
8
  import { RpcTransaction } from "../../../core/jsonrpc/types/output/transaction";
8
9
 
10
+ // the FeeMarketEIP1559TxData interface from ethereum js also has a
11
+ // `gasPrice?: never | null` property, which causes a compilation
12
+ // error in the latest version of typescript
13
+ interface FeeMarketEIP1559TxData extends AccessListEIP2930TxData {
14
+ maxPriorityFeePerGas?: BigIntLike;
15
+ maxFeePerGas?: BigIntLike;
16
+ }
17
+
9
18
  export function rpcToTxData(
10
19
  rpcTransaction: RpcTransaction
11
20
  ): TxData | AccessListEIP2930TxData | FeeMarketEIP1559TxData {