hardhat 2.13.0-dev.2 → 2.13.0-dev.3

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 (292) hide show
  1. package/builtin-tasks/compile.js +16 -6
  2. package/builtin-tasks/compile.js.map +1 -1
  3. package/builtin-tasks/flatten.js +1 -1
  4. package/builtin-tasks/flatten.js.map +1 -1
  5. package/builtin-tasks/help.js +2 -4
  6. package/builtin-tasks/help.js.map +1 -1
  7. package/builtin-tasks/task-names.d.ts +1 -0
  8. package/builtin-tasks/task-names.d.ts.map +1 -1
  9. package/builtin-tasks/task-names.js +3 -2
  10. package/builtin-tasks/task-names.js.map +1 -1
  11. package/builtin-tasks/test.js +22 -1
  12. package/builtin-tasks/test.js.map +1 -1
  13. package/internal/cli/bootstrap.d.ts +1 -0
  14. package/internal/cli/bootstrap.js +12 -20
  15. package/internal/cli/bootstrap.js.map +1 -1
  16. package/internal/cli/cli.d.ts +0 -1
  17. package/internal/cli/cli.d.ts.map +1 -1
  18. package/internal/cli/cli.js +20 -29
  19. package/internal/cli/cli.js.map +1 -1
  20. package/internal/cli/project-creation.d.ts +1 -2
  21. package/internal/cli/project-creation.d.ts.map +1 -1
  22. package/internal/cli/project-creation.js +105 -36
  23. package/internal/cli/project-creation.js.map +1 -1
  24. package/internal/cli/prompt.d.ts +2 -2
  25. package/internal/cli/prompt.d.ts.map +1 -1
  26. package/internal/cli/prompt.js +1 -2
  27. package/internal/cli/prompt.js.map +1 -1
  28. package/internal/cli/types.d.ts +1 -0
  29. package/internal/cli/types.d.ts.map +1 -1
  30. package/internal/core/config/config-env.d.ts +5 -11
  31. package/internal/core/config/config-env.d.ts.map +1 -1
  32. package/internal/core/config/config-env.js +2 -13
  33. package/internal/core/config/config-env.js.map +1 -1
  34. package/internal/core/config/config-loading.d.ts +2 -1
  35. package/internal/core/config/config-loading.d.ts.map +1 -1
  36. package/internal/core/config/config-loading.js +25 -7
  37. package/internal/core/config/config-loading.js.map +1 -1
  38. package/internal/core/config/config-validation.d.ts +2 -0
  39. package/internal/core/config/config-validation.d.ts.map +1 -1
  40. package/internal/core/config/config-validation.js +18 -1
  41. package/internal/core/config/config-validation.js.map +1 -1
  42. package/internal/core/config/extenders.d.ts +4 -7
  43. package/internal/core/config/extenders.d.ts.map +1 -1
  44. package/internal/core/config/extenders.js +5 -12
  45. package/internal/core/config/extenders.js.map +1 -1
  46. package/internal/core/errors-list.d.ts +28 -7
  47. package/internal/core/errors-list.d.ts.map +1 -1
  48. package/internal/core/errors-list.js +33 -10
  49. package/internal/core/errors-list.js.map +1 -1
  50. package/internal/core/jsonrpc/types/input/blockTag.d.ts +3 -3
  51. package/internal/core/jsonrpc/types/input/blockTag.d.ts.map +1 -1
  52. package/internal/core/project-structure.d.ts.map +1 -1
  53. package/internal/core/project-structure.js +6 -0
  54. package/internal/core/project-structure.js.map +1 -1
  55. package/internal/core/providers/construction.d.ts.map +1 -1
  56. package/internal/core/providers/construction.js +25 -5
  57. package/internal/core/providers/construction.js.map +1 -1
  58. package/internal/core/providers/http.d.ts +2 -2
  59. package/internal/core/providers/http.d.ts.map +1 -1
  60. package/internal/core/providers/http.js +41 -19
  61. package/internal/core/providers/http.js.map +1 -1
  62. package/internal/core/runtime-environment.d.ts +4 -2
  63. package/internal/core/runtime-environment.d.ts.map +1 -1
  64. package/internal/core/runtime-environment.js +39 -47
  65. package/internal/core/runtime-environment.js.map +1 -1
  66. package/internal/core/tasks/dsl.d.ts +6 -6
  67. package/internal/core/tasks/dsl.d.ts.map +1 -1
  68. package/internal/core/tasks/dsl.js.map +1 -1
  69. package/internal/core/tasks/task-definitions.d.ts +2 -2
  70. package/internal/core/tasks/task-definitions.d.ts.map +1 -1
  71. package/internal/core/tasks/task-definitions.js.map +1 -1
  72. package/internal/hardhat-network/jsonrpc/handler.d.ts +1 -0
  73. package/internal/hardhat-network/jsonrpc/handler.d.ts.map +1 -1
  74. package/internal/hardhat-network/jsonrpc/handler.js +13 -18
  75. package/internal/hardhat-network/jsonrpc/handler.js.map +1 -1
  76. package/internal/hardhat-network/provider/RethnetState.d.ts +26 -0
  77. package/internal/hardhat-network/provider/RethnetState.d.ts.map +1 -0
  78. package/internal/hardhat-network/provider/RethnetState.js +84 -0
  79. package/internal/hardhat-network/provider/RethnetState.js.map +1 -0
  80. package/internal/hardhat-network/provider/modules/evm.d.ts +2 -1
  81. package/internal/hardhat-network/provider/modules/evm.d.ts.map +1 -1
  82. package/internal/hardhat-network/provider/modules/evm.js +10 -4
  83. package/internal/hardhat-network/provider/modules/evm.js.map +1 -1
  84. package/internal/hardhat-network/provider/node-types.d.ts +1 -1
  85. package/internal/hardhat-network/provider/node-types.d.ts.map +1 -1
  86. package/internal/hardhat-network/provider/node.d.ts +1 -0
  87. package/internal/hardhat-network/provider/node.d.ts.map +1 -1
  88. package/internal/hardhat-network/provider/node.js +6 -4
  89. package/internal/hardhat-network/provider/node.js.map +1 -1
  90. package/internal/hardhat-network/provider/provider.d.ts +25 -21
  91. package/internal/hardhat-network/provider/provider.d.ts.map +1 -1
  92. package/internal/hardhat-network/provider/provider.js +25 -42
  93. package/internal/hardhat-network/provider/provider.js.map +1 -1
  94. package/internal/hardhat-network/provider/return-data.js +2 -2
  95. package/internal/hardhat-network/provider/return-data.js.map +1 -1
  96. package/internal/hardhat-network/provider/transactions/FakeSenderAccessListEIP2930Transaction.d.ts.map +1 -1
  97. package/internal/hardhat-network/provider/transactions/FakeSenderAccessListEIP2930Transaction.js +4 -2
  98. package/internal/hardhat-network/provider/transactions/FakeSenderAccessListEIP2930Transaction.js.map +1 -1
  99. package/internal/hardhat-network/provider/transactions/FakeSenderEIP1559Transaction.d.ts.map +1 -1
  100. package/internal/hardhat-network/provider/transactions/FakeSenderEIP1559Transaction.js +4 -2
  101. package/internal/hardhat-network/provider/transactions/FakeSenderEIP1559Transaction.js.map +1 -1
  102. package/internal/hardhat-network/provider/transactions/FakeSenderTransaction.d.ts.map +1 -1
  103. package/internal/hardhat-network/provider/transactions/FakeSenderTransaction.js +4 -2
  104. package/internal/hardhat-network/provider/transactions/FakeSenderTransaction.js.map +1 -1
  105. package/internal/hardhat-network/provider/utils/bloom.d.ts +32 -0
  106. package/internal/hardhat-network/provider/utils/bloom.d.ts.map +1 -0
  107. package/internal/hardhat-network/provider/utils/bloom.js +79 -0
  108. package/internal/hardhat-network/provider/utils/bloom.js.map +1 -0
  109. package/internal/hardhat-network/provider/utils/convertToRethnet.d.ts +12 -0
  110. package/internal/hardhat-network/provider/utils/convertToRethnet.d.ts.map +1 -0
  111. package/internal/hardhat-network/provider/utils/convertToRethnet.js +162 -0
  112. package/internal/hardhat-network/provider/utils/convertToRethnet.js.map +1 -0
  113. package/internal/hardhat-network/provider/utils/makeFakeSignature.d.ts +7 -0
  114. package/internal/hardhat-network/provider/utils/makeFakeSignature.d.ts.map +1 -0
  115. package/internal/hardhat-network/provider/utils/makeFakeSignature.js +31 -0
  116. package/internal/hardhat-network/provider/utils/makeFakeSignature.js.map +1 -0
  117. package/internal/hardhat-network/provider/utils/putGenesisBlock.d.ts +1 -1
  118. package/internal/hardhat-network/provider/utils/putGenesisBlock.d.ts.map +1 -1
  119. package/internal/hardhat-network/provider/utils/putGenesisBlock.js +2 -2
  120. package/internal/hardhat-network/provider/utils/putGenesisBlock.js.map +1 -1
  121. package/internal/hardhat-network/provider/vm/block-builder.d.ts +31 -0
  122. package/internal/hardhat-network/provider/vm/block-builder.d.ts.map +1 -0
  123. package/internal/hardhat-network/provider/vm/block-builder.js +151 -0
  124. package/internal/hardhat-network/provider/vm/block-builder.js.map +1 -0
  125. package/internal/hardhat-network/provider/vm/creation.d.ts +10 -0
  126. package/internal/hardhat-network/provider/vm/creation.d.ts.map +1 -0
  127. package/internal/hardhat-network/provider/vm/creation.js +29 -0
  128. package/internal/hardhat-network/provider/vm/creation.js.map +1 -0
  129. package/internal/hardhat-network/provider/vm/dual.d.ts +43 -0
  130. package/internal/hardhat-network/provider/vm/dual.d.ts.map +1 -0
  131. package/internal/hardhat-network/provider/vm/dual.js +488 -0
  132. package/internal/hardhat-network/provider/vm/dual.js.map +1 -0
  133. package/internal/hardhat-network/provider/vm/ethereumjs.d.ts +56 -0
  134. package/internal/hardhat-network/provider/vm/ethereumjs.d.ts.map +1 -0
  135. package/internal/hardhat-network/provider/vm/ethereumjs.js +416 -0
  136. package/internal/hardhat-network/provider/vm/ethereumjs.js.map +1 -0
  137. package/internal/hardhat-network/provider/vm/exit.d.ts +23 -0
  138. package/internal/hardhat-network/provider/vm/exit.d.ts.map +1 -0
  139. package/internal/hardhat-network/provider/vm/exit.js +130 -0
  140. package/internal/hardhat-network/provider/vm/exit.js.map +1 -0
  141. package/internal/hardhat-network/provider/vm/rethnet.d.ts +99 -0
  142. package/internal/hardhat-network/provider/vm/rethnet.d.ts.map +1 -0
  143. package/internal/hardhat-network/provider/vm/rethnet.js +284 -0
  144. package/internal/hardhat-network/provider/vm/rethnet.js.map +1 -0
  145. package/internal/hardhat-network/provider/vm/vm-adapter.d.ts +52 -0
  146. package/internal/hardhat-network/provider/vm/vm-adapter.d.ts.map +1 -0
  147. package/internal/hardhat-network/provider/vm/vm-adapter.js +3 -0
  148. package/internal/hardhat-network/provider/vm/vm-adapter.js.map +1 -0
  149. package/internal/hardhat-network/stack-traces/compiler-to-model.d.ts.map +1 -1
  150. package/internal/hardhat-network/stack-traces/compiler-to-model.js +37 -11
  151. package/internal/hardhat-network/stack-traces/compiler-to-model.js.map +1 -1
  152. package/internal/hardhat-network/stack-traces/consoleLogger.js.map +1 -1
  153. package/internal/hardhat-network/stack-traces/constants.d.ts +1 -1
  154. package/internal/hardhat-network/stack-traces/constants.js +1 -1
  155. package/internal/hardhat-network/stack-traces/debug.d.ts.map +1 -1
  156. package/internal/hardhat-network/stack-traces/debug.js +6 -2
  157. package/internal/hardhat-network/stack-traces/debug.js.map +1 -1
  158. package/internal/hardhat-network/stack-traces/error-inferrer.d.ts +1 -0
  159. package/internal/hardhat-network/stack-traces/error-inferrer.d.ts.map +1 -1
  160. package/internal/hardhat-network/stack-traces/error-inferrer.js +85 -55
  161. package/internal/hardhat-network/stack-traces/error-inferrer.js.map +1 -1
  162. package/internal/hardhat-network/stack-traces/model.d.ts +3 -1
  163. package/internal/hardhat-network/stack-traces/model.d.ts.map +1 -1
  164. package/internal/hardhat-network/stack-traces/model.js +9 -1
  165. package/internal/hardhat-network/stack-traces/model.js.map +1 -1
  166. package/internal/hardhat-network/stack-traces/solidity-errors.js +2 -2
  167. package/internal/hardhat-network/stack-traces/solidity-errors.js.map +1 -1
  168. package/internal/hardhat-network/stack-traces/solidity-stack-trace.d.ts +2 -2
  169. package/internal/hardhat-network/stack-traces/solidity-stack-trace.d.ts.map +1 -1
  170. package/internal/hardhat-network/stack-traces/solidityTracer.d.ts.map +1 -1
  171. package/internal/hardhat-network/stack-traces/solidityTracer.js +1 -0
  172. package/internal/hardhat-network/stack-traces/solidityTracer.js.map +1 -1
  173. package/internal/lib/hardhat-lib.d.ts.map +1 -1
  174. package/internal/lib/hardhat-lib.js +1 -4
  175. package/internal/lib/hardhat-lib.js.map +1 -1
  176. package/internal/solidity/compiler/downloader.js +2 -2
  177. package/internal/solidity/compiler/downloader.js.map +1 -1
  178. package/internal/solidity/compiler/index.js +1 -1
  179. package/internal/solidity/compiler/index.js.map +1 -1
  180. package/internal/solidity/resolver.d.ts +4 -3
  181. package/internal/solidity/resolver.d.ts.map +1 -1
  182. package/internal/solidity/resolver.js +18 -7
  183. package/internal/solidity/resolver.js.map +1 -1
  184. package/internal/util/abi-helpers.d.ts +1 -0
  185. package/internal/util/abi-helpers.d.ts.map +1 -1
  186. package/internal/util/abi-helpers.js +9 -0
  187. package/internal/util/abi-helpers.js.map +1 -1
  188. package/internal/util/download.d.ts.map +1 -1
  189. package/internal/util/download.js +12 -11
  190. package/internal/util/download.js.map +1 -1
  191. package/internal/util/packageInfo.d.ts +6 -1
  192. package/internal/util/packageInfo.d.ts.map +1 -1
  193. package/internal/util/packageInfo.js +14 -11
  194. package/internal/util/packageInfo.js.map +1 -1
  195. package/internal/util/proxy.d.ts +2 -0
  196. package/internal/util/proxy.d.ts.map +1 -0
  197. package/internal/util/proxy.js +19 -0
  198. package/internal/util/proxy.js.map +1 -0
  199. package/package.json +9 -10
  200. package/register.js +1 -4
  201. package/register.js.map +1 -1
  202. package/sample-projects/javascript/hardhat.config.js +1 -1
  203. package/sample-projects/javascript/scripts/deploy.js +2 -2
  204. package/sample-projects/javascript-esm/LICENSE.md +11 -0
  205. package/sample-projects/javascript-esm/README.md +13 -0
  206. package/sample-projects/javascript-esm/contracts/Lock.sol +34 -0
  207. package/sample-projects/javascript-esm/hardhat.config.cjs +6 -0
  208. package/sample-projects/javascript-esm/scripts/deploy.js +22 -0
  209. package/sample-projects/javascript-esm/test/Lock.js +123 -0
  210. package/sample-projects/typescript/hardhat.config.ts +1 -1
  211. package/sample-projects/typescript/scripts/deploy.ts +2 -2
  212. package/sample-projects/typescript/tsconfig.json +2 -1
  213. package/src/builtin-tasks/compile.ts +28 -7
  214. package/src/builtin-tasks/flatten.ts +4 -1
  215. package/src/builtin-tasks/help.ts +15 -16
  216. package/src/builtin-tasks/task-names.ts +2 -0
  217. package/src/builtin-tasks/test.ts +30 -2
  218. package/src/internal/artifacts.ts +947 -0
  219. package/src/internal/cli/bootstrap.ts +14 -36
  220. package/src/internal/cli/cli.ts +38 -43
  221. package/src/internal/cli/project-creation.ts +128 -47
  222. package/src/internal/cli/prompt.ts +2 -4
  223. package/src/internal/cli/types.ts +2 -0
  224. package/src/internal/core/config/config-env.ts +15 -27
  225. package/src/internal/core/config/config-loading.ts +35 -11
  226. package/src/internal/core/config/config-validation.ts +20 -0
  227. package/src/internal/core/config/extenders.ts +6 -15
  228. package/src/internal/core/errors-list.ts +36 -10
  229. package/src/internal/core/project-structure.ts +8 -0
  230. package/src/internal/core/providers/construction.ts +29 -24
  231. package/src/internal/core/providers/http.ts +38 -26
  232. package/src/internal/core/runtime-environment.ts +65 -60
  233. package/src/internal/core/tasks/dsl.ts +17 -17
  234. package/src/internal/core/tasks/task-definitions.ts +6 -2
  235. package/src/internal/hardhat-network/jsonrpc/handler.ts +31 -28
  236. package/src/internal/hardhat-network/provider/modules/evm.ts +15 -3
  237. package/src/internal/hardhat-network/provider/node-types.ts +1 -1
  238. package/src/internal/hardhat-network/provider/node.ts +5 -1
  239. package/src/internal/hardhat-network/provider/provider.ts +60 -49
  240. package/src/internal/hardhat-network/provider/return-data.ts +2 -2
  241. package/src/internal/hardhat-network/provider/transactions/FakeSenderAccessListEIP2930Transaction.ts +5 -2
  242. package/src/internal/hardhat-network/provider/transactions/FakeSenderEIP1559Transaction.ts +5 -2
  243. package/src/internal/hardhat-network/provider/transactions/FakeSenderTransaction.ts +5 -2
  244. package/src/internal/hardhat-network/provider/utils/makeFakeSignature.ts +46 -0
  245. package/src/internal/hardhat-network/provider/utils/putGenesisBlock.ts +2 -2
  246. package/src/internal/hardhat-network/stack-traces/compiler-to-model.ts +71 -9
  247. package/src/internal/hardhat-network/stack-traces/consoleLogger.ts +1 -1
  248. package/src/internal/hardhat-network/stack-traces/constants.ts +1 -1
  249. package/src/internal/hardhat-network/stack-traces/debug.ts +9 -2
  250. package/src/internal/hardhat-network/stack-traces/error-inferrer.ts +177 -89
  251. package/src/internal/hardhat-network/stack-traces/model.ts +11 -1
  252. package/src/internal/hardhat-network/stack-traces/solidity-errors.ts +2 -2
  253. package/src/internal/hardhat-network/stack-traces/solidity-stack-trace.ts +2 -2
  254. package/src/internal/hardhat-network/stack-traces/solidityTracer.ts +3 -0
  255. package/src/internal/lib/hardhat-lib.ts +1 -6
  256. package/src/internal/solidity/compiler/downloader.ts +2 -2
  257. package/src/internal/solidity/compiler/index.ts +1 -1
  258. package/src/internal/solidity/resolver.ts +28 -11
  259. package/src/internal/util/abi-helpers.ts +9 -0
  260. package/src/internal/util/download.ts +13 -15
  261. package/src/internal/util/packageInfo.ts +24 -10
  262. package/src/internal/util/proxy.ts +18 -0
  263. package/src/register.ts +1 -6
  264. package/src/types/artifacts.ts +14 -112
  265. package/src/types/config.ts +2 -0
  266. package/src/types/runtime.ts +16 -13
  267. package/types/artifacts.d.ts +10 -96
  268. package/types/artifacts.d.ts.map +1 -1
  269. package/types/config.d.ts +2 -0
  270. package/types/config.d.ts.map +1 -1
  271. package/types/runtime.d.ts +9 -10
  272. package/types/runtime.d.ts.map +1 -1
  273. package/internal/artifacts/caching.d.ts +0 -28
  274. package/internal/artifacts/caching.d.ts.map +0 -1
  275. package/internal/artifacts/caching.js +0 -178
  276. package/internal/artifacts/caching.js.map +0 -1
  277. package/internal/artifacts/index.d.ts +0 -45
  278. package/internal/artifacts/index.d.ts.map +0 -1
  279. package/internal/artifacts/index.js +0 -191
  280. package/internal/artifacts/index.js.map +0 -1
  281. package/internal/artifacts/mutable.d.ts +0 -29
  282. package/internal/artifacts/mutable.d.ts.map +0 -1
  283. package/internal/artifacts/mutable.js +0 -226
  284. package/internal/artifacts/mutable.js.map +0 -1
  285. package/internal/artifacts/readonly.d.ts +0 -94
  286. package/internal/artifacts/readonly.d.ts.map +0 -1
  287. package/internal/artifacts/readonly.js +0 -343
  288. package/internal/artifacts/readonly.js.map +0 -1
  289. package/src/internal/artifacts/caching.ts +0 -259
  290. package/src/internal/artifacts/index.ts +0 -302
  291. package/src/internal/artifacts/mutable.ts +0 -330
  292. package/src/internal/artifacts/readonly.ts +0 -470
@@ -0,0 +1,947 @@
1
+ import debug from "debug";
2
+ import fsExtra from "fs-extra";
3
+ import * as os from "os";
4
+ import * as path from "path";
5
+ import fsPromises from "fs/promises";
6
+
7
+ import {
8
+ Artifact,
9
+ Artifacts as IArtifacts,
10
+ BuildInfo,
11
+ CompilerInput,
12
+ CompilerOutput,
13
+ DebugFile,
14
+ } from "../types";
15
+ import {
16
+ getFullyQualifiedName,
17
+ isFullyQualifiedName,
18
+ parseFullyQualifiedName,
19
+ findDistance,
20
+ } from "../utils/contract-names";
21
+ import { replaceBackslashes } from "../utils/source-names";
22
+
23
+ import {
24
+ ARTIFACT_FORMAT_VERSION,
25
+ BUILD_INFO_DIR_NAME,
26
+ BUILD_INFO_FORMAT_VERSION,
27
+ DEBUG_FILE_FORMAT_VERSION,
28
+ EDIT_DISTANCE_THRESHOLD,
29
+ } from "./constants";
30
+ import { HardhatError } from "./core/errors";
31
+ import { ERRORS } from "./core/errors-list";
32
+ import { createNonCryptographicHashBasedIdentifier } from "./util/hash";
33
+ import {
34
+ FileNotFoundError,
35
+ getAllFilesMatching,
36
+ getAllFilesMatchingSync,
37
+ getFileTrueCase,
38
+ getFileTrueCaseSync,
39
+ } from "./util/fs-utils";
40
+
41
+ const log = debug("hardhat:core:artifacts");
42
+
43
+ interface Cache {
44
+ artifactPaths?: string[];
45
+ debugFilePaths?: string[];
46
+ buildInfoPaths?: string[];
47
+ artifactNameToArtifactPathCache: Map<string, string>;
48
+ artifactFQNToBuildInfoPathCache: Map<string, string>;
49
+ }
50
+
51
+ export class Artifacts implements IArtifacts {
52
+ private _validArtifacts: Array<{ sourceName: string; artifacts: string[] }>;
53
+
54
+ // Undefined means that the cache is disabled.
55
+ private _cache?: Cache = {
56
+ artifactNameToArtifactPathCache: new Map(),
57
+ artifactFQNToBuildInfoPathCache: new Map(),
58
+ };
59
+
60
+ constructor(private _artifactsPath: string) {
61
+ this._validArtifacts = [];
62
+ }
63
+
64
+ public addValidArtifacts(
65
+ validArtifacts: Array<{ sourceName: string; artifacts: string[] }>
66
+ ) {
67
+ this._validArtifacts.push(...validArtifacts);
68
+ }
69
+
70
+ public async readArtifact(name: string): Promise<Artifact> {
71
+ const artifactPath = await this._getArtifactPath(name);
72
+ return fsExtra.readJson(artifactPath);
73
+ }
74
+
75
+ public readArtifactSync(name: string): Artifact {
76
+ const artifactPath = this._getArtifactPathSync(name);
77
+ return fsExtra.readJsonSync(artifactPath);
78
+ }
79
+
80
+ public async artifactExists(name: string): Promise<boolean> {
81
+ const artifactPath = await this._getArtifactPath(name);
82
+ return fsExtra.pathExists(artifactPath);
83
+ }
84
+
85
+ public async getAllFullyQualifiedNames(): Promise<string[]> {
86
+ const paths = await this.getArtifactPaths();
87
+ return paths.map((p) => this._getFullyQualifiedNameFromPath(p)).sort();
88
+ }
89
+
90
+ public async getBuildInfo(
91
+ fullyQualifiedName: string
92
+ ): Promise<BuildInfo | undefined> {
93
+ let buildInfoPath =
94
+ this._cache?.artifactFQNToBuildInfoPathCache.get(fullyQualifiedName);
95
+
96
+ if (buildInfoPath === undefined) {
97
+ const artifactPath =
98
+ this.formArtifactPathFromFullyQualifiedName(fullyQualifiedName);
99
+
100
+ const debugFilePath = this._getDebugFilePath(artifactPath);
101
+ buildInfoPath = await this._getBuildInfoFromDebugFile(debugFilePath);
102
+
103
+ if (buildInfoPath === undefined) {
104
+ return undefined;
105
+ }
106
+
107
+ this._cache?.artifactFQNToBuildInfoPathCache.set(
108
+ fullyQualifiedName,
109
+ buildInfoPath
110
+ );
111
+ }
112
+
113
+ return fsExtra.readJSON(buildInfoPath);
114
+ }
115
+
116
+ public getBuildInfoSync(fullyQualifiedName: string): BuildInfo | undefined {
117
+ let buildInfoPath =
118
+ this._cache?.artifactFQNToBuildInfoPathCache.get(fullyQualifiedName);
119
+
120
+ if (buildInfoPath === undefined) {
121
+ const artifactPath =
122
+ this.formArtifactPathFromFullyQualifiedName(fullyQualifiedName);
123
+
124
+ const debugFilePath = this._getDebugFilePath(artifactPath);
125
+ buildInfoPath = this._getBuildInfoFromDebugFileSync(debugFilePath);
126
+
127
+ if (buildInfoPath === undefined) {
128
+ return undefined;
129
+ }
130
+
131
+ this._cache?.artifactFQNToBuildInfoPathCache.set(
132
+ fullyQualifiedName,
133
+ buildInfoPath
134
+ );
135
+ }
136
+
137
+ return fsExtra.readJSONSync(buildInfoPath);
138
+ }
139
+
140
+ public async getArtifactPaths(): Promise<string[]> {
141
+ const cached = this._cache?.artifactPaths;
142
+ if (cached !== undefined) {
143
+ return cached;
144
+ }
145
+
146
+ const buildInfosDir = path.join(this._artifactsPath, BUILD_INFO_DIR_NAME);
147
+
148
+ const paths = await getAllFilesMatching(
149
+ this._artifactsPath,
150
+ (f) =>
151
+ f.endsWith(".json") &&
152
+ !f.startsWith(buildInfosDir) &&
153
+ !f.endsWith(".dbg.json")
154
+ );
155
+
156
+ const result = paths.sort();
157
+
158
+ if (this._cache !== undefined) {
159
+ this._cache.artifactPaths = result;
160
+ }
161
+
162
+ return result;
163
+ }
164
+
165
+ public async getBuildInfoPaths(): Promise<string[]> {
166
+ const cached = this._cache?.buildInfoPaths;
167
+ if (cached !== undefined) {
168
+ return cached;
169
+ }
170
+
171
+ const paths = await getAllFilesMatching(
172
+ path.join(this._artifactsPath, BUILD_INFO_DIR_NAME),
173
+ (f) => f.endsWith(".json")
174
+ );
175
+
176
+ const result = paths.sort();
177
+
178
+ if (this._cache !== undefined) {
179
+ this._cache.buildInfoPaths = result;
180
+ }
181
+
182
+ return result;
183
+ }
184
+
185
+ public async getDebugFilePaths(): Promise<string[]> {
186
+ const cached = this._cache?.debugFilePaths;
187
+ if (cached !== undefined) {
188
+ return cached;
189
+ }
190
+
191
+ const paths = await getAllFilesMatching(
192
+ path.join(this._artifactsPath),
193
+ (f) => f.endsWith(".dbg.json")
194
+ );
195
+
196
+ const result = paths.sort();
197
+
198
+ if (this._cache !== undefined) {
199
+ this._cache.debugFilePaths = result;
200
+ }
201
+
202
+ return result;
203
+ }
204
+
205
+ public async saveArtifactAndDebugFile(
206
+ artifact: Artifact,
207
+ pathToBuildInfo?: string
208
+ ) {
209
+ try {
210
+ // artifact
211
+ const fullyQualifiedName = getFullyQualifiedName(
212
+ artifact.sourceName,
213
+ artifact.contractName
214
+ );
215
+
216
+ const artifactPath =
217
+ this.formArtifactPathFromFullyQualifiedName(fullyQualifiedName);
218
+
219
+ await fsExtra.ensureDir(path.dirname(artifactPath));
220
+
221
+ await Promise.all([
222
+ fsExtra.writeJSON(artifactPath, artifact, {
223
+ spaces: 2,
224
+ }),
225
+ (async () => {
226
+ if (pathToBuildInfo === undefined) {
227
+ return;
228
+ }
229
+
230
+ // save debug file
231
+ const debugFilePath = this._getDebugFilePath(artifactPath);
232
+ const debugFile = this._createDebugFile(
233
+ artifactPath,
234
+ pathToBuildInfo
235
+ );
236
+
237
+ await fsExtra.writeJSON(debugFilePath, debugFile, {
238
+ spaces: 2,
239
+ });
240
+ })(),
241
+ ]);
242
+ } finally {
243
+ this.clearCache();
244
+ }
245
+ }
246
+
247
+ public async saveBuildInfo(
248
+ solcVersion: string,
249
+ solcLongVersion: string,
250
+ input: CompilerInput,
251
+ output: CompilerOutput
252
+ ): Promise<string> {
253
+ try {
254
+ const buildInfoDir = path.join(this._artifactsPath, BUILD_INFO_DIR_NAME);
255
+ await fsExtra.ensureDir(buildInfoDir);
256
+
257
+ const buildInfoName = this._getBuildInfoName(
258
+ solcVersion,
259
+ solcLongVersion,
260
+ input
261
+ );
262
+
263
+ const buildInfo = this._createBuildInfo(
264
+ buildInfoName,
265
+ solcVersion,
266
+ solcLongVersion,
267
+ input,
268
+ output
269
+ );
270
+
271
+ const buildInfoPath = path.join(buildInfoDir, `${buildInfoName}.json`);
272
+
273
+ // JSON.stringify of the entire build info can be really slow
274
+ // in larger projects, so we stringify per part and incrementally create
275
+ // the JSON in the file.
276
+ //
277
+ // We split this code into different curly-brace-enclosed scopes so that
278
+ // partial JSON strings get out of scope sooner and hence can be reclaimed
279
+ // by the GC if needed.
280
+ const file = await fsPromises.open(buildInfoPath, "w");
281
+ try {
282
+ {
283
+ const withoutOutput = JSON.stringify({
284
+ ...buildInfo,
285
+ output: undefined,
286
+ });
287
+
288
+ // We write the JSON (without output) except the last }
289
+ await file.write(withoutOutput.slice(0, -1));
290
+ }
291
+
292
+ {
293
+ const outputWithoutSourcesAndContracts = JSON.stringify({
294
+ ...buildInfo.output,
295
+ sources: undefined,
296
+ contracts: undefined,
297
+ });
298
+
299
+ // We start writing the output
300
+ await file.write(',"output":');
301
+
302
+ // Write the output object except for the last }
303
+ await file.write(outputWithoutSourcesAndContracts.slice(0, -1));
304
+
305
+ // If there were other field apart from sources and contracts we need
306
+ // a comma
307
+ if (outputWithoutSourcesAndContracts.length > 2) {
308
+ await file.write(",");
309
+ }
310
+ }
311
+
312
+ // Writing the sources
313
+ await file.write('"sources":{');
314
+
315
+ let isFirst = true;
316
+ for (const [name, value] of Object.entries(
317
+ buildInfo.output.sources ?? {}
318
+ )) {
319
+ if (isFirst) {
320
+ isFirst = false;
321
+ } else {
322
+ await file.write(",");
323
+ }
324
+
325
+ await file.write(`${JSON.stringify(name)}:${JSON.stringify(value)}`);
326
+ }
327
+
328
+ // Close sources object
329
+ await file.write("}");
330
+
331
+ // Writing the contracts
332
+ await file.write(',"contracts":{');
333
+
334
+ isFirst = true;
335
+ for (const [name, value] of Object.entries(
336
+ buildInfo.output.contracts ?? {}
337
+ )) {
338
+ if (isFirst) {
339
+ isFirst = false;
340
+ } else {
341
+ await file.write(",");
342
+ }
343
+
344
+ await file.write(`${JSON.stringify(name)}:${JSON.stringify(value)}`);
345
+ }
346
+
347
+ // close contracts object
348
+ await file.write("}");
349
+ // close output object
350
+ await file.write("}");
351
+ // close build info object
352
+ await file.write("}");
353
+ } finally {
354
+ await file.close();
355
+ }
356
+
357
+ return buildInfoPath;
358
+ } finally {
359
+ this.clearCache();
360
+ }
361
+ }
362
+
363
+ /**
364
+ * Remove all artifacts that don't correspond to the current solidity files
365
+ */
366
+ public async removeObsoleteArtifacts() {
367
+ // We clear the cache here, as we want to be sure this runs correctly
368
+ this.clearCache();
369
+
370
+ try {
371
+ const validArtifactPaths = await Promise.all(
372
+ this._validArtifacts.flatMap(({ sourceName, artifacts }) =>
373
+ artifacts.map((artifactName) =>
374
+ this._getArtifactPath(
375
+ getFullyQualifiedName(sourceName, artifactName)
376
+ )
377
+ )
378
+ )
379
+ );
380
+
381
+ const validArtifactsPathsSet = new Set<string>(validArtifactPaths);
382
+
383
+ for (const { sourceName, artifacts } of this._validArtifacts) {
384
+ for (const artifactName of artifacts) {
385
+ validArtifactsPathsSet.add(
386
+ this.formArtifactPathFromFullyQualifiedName(
387
+ getFullyQualifiedName(sourceName, artifactName)
388
+ )
389
+ );
390
+ }
391
+ }
392
+
393
+ const existingArtifactsPaths = await this.getArtifactPaths();
394
+
395
+ await Promise.all(
396
+ existingArtifactsPaths
397
+ .filter((artifactPath) => !validArtifactsPathsSet.has(artifactPath))
398
+ .map((artifactPath) => this._removeArtifactFiles(artifactPath))
399
+ );
400
+
401
+ await this._removeObsoleteBuildInfos();
402
+ } finally {
403
+ // We clear the cache here, as this may have non-existent paths now
404
+ this.clearCache();
405
+ }
406
+ }
407
+
408
+ /**
409
+ * Returns the absolute path to the given artifact
410
+ */
411
+ public formArtifactPathFromFullyQualifiedName(
412
+ fullyQualifiedName: string
413
+ ): string {
414
+ const { sourceName, contractName } =
415
+ parseFullyQualifiedName(fullyQualifiedName);
416
+
417
+ return path.join(this._artifactsPath, sourceName, `${contractName}.json`);
418
+ }
419
+
420
+ public clearCache() {
421
+ // Avoid accidentally re-enabling the cache
422
+ if (this._cache === undefined) {
423
+ return;
424
+ }
425
+
426
+ this._cache = {
427
+ artifactFQNToBuildInfoPathCache: new Map(),
428
+ artifactNameToArtifactPathCache: new Map(),
429
+ };
430
+ }
431
+
432
+ public disableCache() {
433
+ this._cache = undefined;
434
+ }
435
+
436
+ /**
437
+ * Remove all build infos that aren't used by any debug file
438
+ */
439
+ private async _removeObsoleteBuildInfos() {
440
+ const debugFiles = await this.getDebugFilePaths();
441
+
442
+ const buildInfos = await Promise.all(
443
+ debugFiles.map(async (debugFile) => {
444
+ const buildInfoFile = await this._getBuildInfoFromDebugFile(debugFile);
445
+ if (buildInfoFile !== undefined) {
446
+ return path.resolve(path.dirname(debugFile), buildInfoFile);
447
+ } else {
448
+ return undefined;
449
+ }
450
+ })
451
+ );
452
+
453
+ const filteredBuildInfos: string[] = buildInfos.filter(
454
+ (bf): bf is string => typeof bf === "string"
455
+ );
456
+
457
+ const validBuildInfos = new Set<string>(filteredBuildInfos);
458
+
459
+ const buildInfoFiles = await this.getBuildInfoPaths();
460
+
461
+ await Promise.all(
462
+ buildInfoFiles
463
+ .filter((buildInfoFile) => !validBuildInfos.has(buildInfoFile))
464
+ .map(async (buildInfoFile) => {
465
+ log(`Removing buildInfo '${buildInfoFile}'`);
466
+ await fsExtra.unlink(buildInfoFile);
467
+ })
468
+ );
469
+ }
470
+
471
+ private _getBuildInfoName(
472
+ solcVersion: string,
473
+ solcLongVersion: string,
474
+ input: CompilerInput
475
+ ): string {
476
+ const json = JSON.stringify({
477
+ _format: BUILD_INFO_FORMAT_VERSION,
478
+ solcVersion,
479
+ solcLongVersion,
480
+ input,
481
+ });
482
+
483
+ return createNonCryptographicHashBasedIdentifier(
484
+ Buffer.from(json)
485
+ ).toString("hex");
486
+ }
487
+
488
+ /**
489
+ * Returns the absolute path to the artifact that corresponds to the given
490
+ * name.
491
+ *
492
+ * If the name is fully qualified, the path is computed from it. If not, an
493
+ * artifact that matches the given name is searched in the existing artifacts.
494
+ * If there is an ambiguity, an error is thrown.
495
+ */
496
+ private async _getArtifactPath(name: string): Promise<string> {
497
+ const cached = this._cache?.artifactNameToArtifactPathCache.get(name);
498
+ if (cached !== undefined) {
499
+ return cached;
500
+ }
501
+
502
+ let result: string;
503
+ if (isFullyQualifiedName(name)) {
504
+ result = await this._getValidArtifactPathFromFullyQualifiedName(name);
505
+ } else {
506
+ const files = await this.getArtifactPaths();
507
+ result = this._getArtifactPathFromFiles(name, files);
508
+ }
509
+
510
+ this._cache?.artifactNameToArtifactPathCache.set(name, result);
511
+ return result;
512
+ }
513
+
514
+ private _createBuildInfo(
515
+ id: string,
516
+ solcVersion: string,
517
+ solcLongVersion: string,
518
+ input: CompilerInput,
519
+ output: CompilerOutput
520
+ ): BuildInfo {
521
+ return {
522
+ id,
523
+ _format: BUILD_INFO_FORMAT_VERSION,
524
+ solcVersion,
525
+ solcLongVersion,
526
+ input,
527
+ output,
528
+ };
529
+ }
530
+
531
+ private _createDebugFile(artifactPath: string, pathToBuildInfo: string) {
532
+ const relativePathToBuildInfo = path.relative(
533
+ path.dirname(artifactPath),
534
+ pathToBuildInfo
535
+ );
536
+
537
+ const debugFile: DebugFile = {
538
+ _format: DEBUG_FILE_FORMAT_VERSION,
539
+ buildInfo: relativePathToBuildInfo,
540
+ };
541
+
542
+ return debugFile;
543
+ }
544
+
545
+ private _getArtifactPathsSync(): string[] {
546
+ const cached = this._cache?.artifactPaths;
547
+ if (cached !== undefined) {
548
+ return cached;
549
+ }
550
+
551
+ const buildInfosDir = path.join(this._artifactsPath, BUILD_INFO_DIR_NAME);
552
+
553
+ const paths = getAllFilesMatchingSync(
554
+ this._artifactsPath,
555
+ (f) =>
556
+ f.endsWith(".json") &&
557
+ !f.startsWith(buildInfosDir) &&
558
+ !f.endsWith(".dbg.json")
559
+ );
560
+
561
+ const result = paths.sort();
562
+
563
+ if (this._cache !== undefined) {
564
+ this._cache.artifactPaths = result;
565
+ }
566
+
567
+ return result;
568
+ }
569
+
570
+ /**
571
+ * Sync version of _getArtifactPath
572
+ */
573
+ private _getArtifactPathSync(name: string): string {
574
+ const cached = this._cache?.artifactNameToArtifactPathCache.get(name);
575
+ if (cached !== undefined) {
576
+ return cached;
577
+ }
578
+
579
+ let result: string;
580
+
581
+ if (isFullyQualifiedName(name)) {
582
+ result = this._getValidArtifactPathFromFullyQualifiedNameSync(name);
583
+ } else {
584
+ const files = this._getArtifactPathsSync();
585
+ result = this._getArtifactPathFromFiles(name, files);
586
+ }
587
+
588
+ this._cache?.artifactNameToArtifactPathCache.set(name, result);
589
+ return result;
590
+ }
591
+
592
+ /**
593
+ * DO NOT DELETE OR CHANGE
594
+ *
595
+ * use this.formArtifactPathFromFullyQualifiedName instead
596
+ * @deprecated until typechain migrates to public version
597
+ * @see https://github.com/dethcrypto/TypeChain/issues/544
598
+ */
599
+ private _getArtifactPathFromFullyQualifiedName(
600
+ fullyQualifiedName: string
601
+ ): string {
602
+ const { sourceName, contractName } =
603
+ parseFullyQualifiedName(fullyQualifiedName);
604
+
605
+ return path.join(this._artifactsPath, sourceName, `${contractName}.json`);
606
+ }
607
+
608
+ private async _getValidArtifactPathFromFullyQualifiedName(
609
+ fullyQualifiedName: string
610
+ ): Promise<string> {
611
+ const artifactPath =
612
+ this.formArtifactPathFromFullyQualifiedName(fullyQualifiedName);
613
+
614
+ try {
615
+ const trueCasePath = path.join(
616
+ this._artifactsPath,
617
+ await getFileTrueCase(
618
+ this._artifactsPath,
619
+ path.relative(this._artifactsPath, artifactPath)
620
+ )
621
+ );
622
+
623
+ if (artifactPath !== trueCasePath) {
624
+ throw new HardhatError(ERRORS.ARTIFACTS.WRONG_CASING, {
625
+ correct: this._getFullyQualifiedNameFromPath(trueCasePath),
626
+ incorrect: fullyQualifiedName,
627
+ });
628
+ }
629
+
630
+ return trueCasePath;
631
+ } catch (e) {
632
+ if (e instanceof FileNotFoundError) {
633
+ return this._handleWrongArtifactForFullyQualifiedName(
634
+ fullyQualifiedName
635
+ );
636
+ }
637
+
638
+ // eslint-disable-next-line @nomiclabs/hardhat-internal-rules/only-hardhat-error
639
+ throw e;
640
+ }
641
+ }
642
+
643
+ private _getAllContractNamesFromFiles(files: string[]): string[] {
644
+ return files.map((file) => {
645
+ const fqn = this._getFullyQualifiedNameFromPath(file);
646
+ return parseFullyQualifiedName(fqn).contractName;
647
+ });
648
+ }
649
+
650
+ private _getAllFullyQualifiedNamesSync(): string[] {
651
+ const paths = this._getArtifactPathsSync();
652
+ return paths.map((p) => this._getFullyQualifiedNameFromPath(p)).sort();
653
+ }
654
+
655
+ private _formatSuggestions(names: string[], contractName: string): string {
656
+ switch (names.length) {
657
+ case 0:
658
+ return "";
659
+ case 1:
660
+ return `Did you mean "${names[0]}"?`;
661
+ default:
662
+ return `We found some that were similar:
663
+
664
+ ${names.map((n) => ` * ${n}`).join(os.EOL)}
665
+
666
+ Please replace "${contractName}" for the correct contract name wherever you are trying to read its artifact.
667
+ `;
668
+ }
669
+ }
670
+
671
+ private _handleWrongArtifactForFullyQualifiedName(
672
+ fullyQualifiedName: string
673
+ ): never {
674
+ const names = this._getAllFullyQualifiedNamesSync();
675
+
676
+ const similarNames = this._getSimilarContractNames(
677
+ fullyQualifiedName,
678
+ names
679
+ );
680
+
681
+ throw new HardhatError(ERRORS.ARTIFACTS.NOT_FOUND, {
682
+ contractName: fullyQualifiedName,
683
+ suggestion: this._formatSuggestions(similarNames, fullyQualifiedName),
684
+ });
685
+ }
686
+
687
+ private _handleWrongArtifactForContractName(
688
+ contractName: string,
689
+ files: string[]
690
+ ): never {
691
+ const names = this._getAllContractNamesFromFiles(files);
692
+
693
+ let similarNames = this._getSimilarContractNames(contractName, names);
694
+
695
+ if (similarNames.length > 1) {
696
+ similarNames = this._filterDuplicatesAsFullyQualifiedNames(
697
+ files,
698
+ similarNames
699
+ );
700
+ }
701
+
702
+ throw new HardhatError(ERRORS.ARTIFACTS.NOT_FOUND, {
703
+ contractName,
704
+ suggestion: this._formatSuggestions(similarNames, contractName),
705
+ });
706
+ }
707
+
708
+ /**
709
+ * If the project has these contracts:
710
+ * - 'contracts/Greeter.sol:Greeter'
711
+ * - 'contracts/Meeter.sol:Greeter'
712
+ * - 'contracts/Greater.sol:Greater'
713
+ * And the user tries to get an artifact with the name 'Greter', then
714
+ * the suggestions will be 'Greeter', 'Greeter', and 'Greater'.
715
+ *
716
+ * We don't want to show duplicates here, so we use FQNs for those. The
717
+ * suggestions will then be:
718
+ * - 'contracts/Greeter.sol:Greeter'
719
+ * - 'contracts/Meeter.sol:Greeter'
720
+ * - 'Greater'
721
+ */
722
+ private _filterDuplicatesAsFullyQualifiedNames(
723
+ files: string[],
724
+ similarNames: string[]
725
+ ): string[] {
726
+ const outputNames = [];
727
+ const groups = similarNames.reduce((obj, cur) => {
728
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
729
+ obj[cur] = obj[cur] ? obj[cur] + 1 : 1;
730
+ return obj;
731
+ }, {} as { [k: string]: number });
732
+
733
+ for (const [name, occurrences] of Object.entries(groups)) {
734
+ if (occurrences > 1) {
735
+ for (const file of files) {
736
+ if (path.basename(file) === `${name}.json`) {
737
+ outputNames.push(this._getFullyQualifiedNameFromPath(file));
738
+ }
739
+ }
740
+ continue;
741
+ }
742
+
743
+ outputNames.push(name);
744
+ }
745
+
746
+ return outputNames;
747
+ }
748
+
749
+ /**
750
+ *
751
+ * @param givenName can be FQN or contract name
752
+ * @param names MUST match type of givenName (i.e. array of FQN's if givenName is FQN)
753
+ * @returns
754
+ */
755
+ private _getSimilarContractNames(
756
+ givenName: string,
757
+ names: string[]
758
+ ): string[] {
759
+ let shortestDistance = EDIT_DISTANCE_THRESHOLD;
760
+ let mostSimilarNames: string[] = [];
761
+ for (const name of names) {
762
+ const distance = findDistance(givenName, name);
763
+
764
+ if (distance < shortestDistance) {
765
+ shortestDistance = distance;
766
+ mostSimilarNames = [name];
767
+ continue;
768
+ }
769
+
770
+ if (distance === shortestDistance) {
771
+ mostSimilarNames.push(name);
772
+ continue;
773
+ }
774
+ }
775
+
776
+ return mostSimilarNames;
777
+ }
778
+
779
+ private _getValidArtifactPathFromFullyQualifiedNameSync(
780
+ fullyQualifiedName: string
781
+ ): string {
782
+ const artifactPath =
783
+ this.formArtifactPathFromFullyQualifiedName(fullyQualifiedName);
784
+
785
+ try {
786
+ const trueCasePath = path.join(
787
+ this._artifactsPath,
788
+ getFileTrueCaseSync(
789
+ this._artifactsPath,
790
+ path.relative(this._artifactsPath, artifactPath)
791
+ )
792
+ );
793
+
794
+ if (artifactPath !== trueCasePath) {
795
+ throw new HardhatError(ERRORS.ARTIFACTS.WRONG_CASING, {
796
+ correct: this._getFullyQualifiedNameFromPath(trueCasePath),
797
+ incorrect: fullyQualifiedName,
798
+ });
799
+ }
800
+
801
+ return trueCasePath;
802
+ } catch (e) {
803
+ if (e instanceof FileNotFoundError) {
804
+ return this._handleWrongArtifactForFullyQualifiedName(
805
+ fullyQualifiedName
806
+ );
807
+ }
808
+
809
+ // eslint-disable-next-line @nomiclabs/hardhat-internal-rules/only-hardhat-error
810
+ throw e;
811
+ }
812
+ }
813
+
814
+ private _getDebugFilePath(artifactPath: string): string {
815
+ return artifactPath.replace(/\.json$/, ".dbg.json");
816
+ }
817
+
818
+ private _getArtifactPathFromFiles(
819
+ contractName: string,
820
+ files: string[]
821
+ ): string {
822
+ const matchingFiles = files.filter((file) => {
823
+ return path.basename(file) === `${contractName}.json`;
824
+ });
825
+
826
+ if (matchingFiles.length === 0) {
827
+ return this._handleWrongArtifactForContractName(contractName, files);
828
+ }
829
+
830
+ if (matchingFiles.length > 1) {
831
+ const candidates = matchingFiles.map((file) =>
832
+ this._getFullyQualifiedNameFromPath(file)
833
+ );
834
+
835
+ throw new HardhatError(ERRORS.ARTIFACTS.MULTIPLE_FOUND, {
836
+ contractName,
837
+ candidates: candidates.join(os.EOL),
838
+ });
839
+ }
840
+
841
+ return matchingFiles[0];
842
+ }
843
+
844
+ /**
845
+ * Returns the FQN of a contract giving the absolute path to its artifact.
846
+ *
847
+ * For example, given a path like
848
+ * `/path/to/project/artifacts/contracts/Foo.sol/Bar.json`, it'll return the
849
+ * FQN `contracts/Foo.sol:Bar`
850
+ */
851
+ private _getFullyQualifiedNameFromPath(absolutePath: string): string {
852
+ const sourceName = replaceBackslashes(
853
+ path.relative(this._artifactsPath, path.dirname(absolutePath))
854
+ );
855
+
856
+ const contractName = path.basename(absolutePath).replace(".json", "");
857
+
858
+ return getFullyQualifiedName(sourceName, contractName);
859
+ }
860
+
861
+ /**
862
+ * Remove the artifact file, its debug file and, if it exists, its build
863
+ * info file.
864
+ */
865
+ private async _removeArtifactFiles(artifactPath: string) {
866
+ await fsExtra.remove(artifactPath);
867
+
868
+ const debugFilePath = this._getDebugFilePath(artifactPath);
869
+ const buildInfoPath = await this._getBuildInfoFromDebugFile(debugFilePath);
870
+
871
+ await fsExtra.remove(debugFilePath);
872
+
873
+ if (buildInfoPath !== undefined) {
874
+ await fsExtra.remove(buildInfoPath);
875
+ }
876
+ }
877
+
878
+ /**
879
+ * Given the path to a debug file, returns the absolute path to its
880
+ * corresponding build info file if it exists, or undefined otherwise.
881
+ */
882
+ private async _getBuildInfoFromDebugFile(
883
+ debugFilePath: string
884
+ ): Promise<string | undefined> {
885
+ if (await fsExtra.pathExists(debugFilePath)) {
886
+ const { buildInfo } = await fsExtra.readJson(debugFilePath);
887
+ return path.resolve(path.dirname(debugFilePath), buildInfo);
888
+ }
889
+
890
+ return undefined;
891
+ }
892
+
893
+ /**
894
+ * Sync version of _getBuildInfoFromDebugFile
895
+ */
896
+ private _getBuildInfoFromDebugFileSync(
897
+ debugFilePath: string
898
+ ): string | undefined {
899
+ if (fsExtra.pathExistsSync(debugFilePath)) {
900
+ const { buildInfo } = fsExtra.readJsonSync(debugFilePath);
901
+ return path.resolve(path.dirname(debugFilePath), buildInfo);
902
+ }
903
+
904
+ return undefined;
905
+ }
906
+ }
907
+
908
+ /**
909
+ * Retrieves an artifact for the given `contractName` from the compilation output.
910
+ *
911
+ * @param sourceName The contract's source name.
912
+ * @param contractName the contract's name.
913
+ * @param contractOutput the contract's compilation output as emitted by `solc`.
914
+ */
915
+ export function getArtifactFromContractOutput(
916
+ sourceName: string,
917
+ contractName: string,
918
+ contractOutput: any
919
+ ): Artifact {
920
+ const evmBytecode = contractOutput.evm?.bytecode;
921
+ let bytecode: string = evmBytecode?.object ?? "";
922
+
923
+ if (bytecode.slice(0, 2).toLowerCase() !== "0x") {
924
+ bytecode = `0x${bytecode}`;
925
+ }
926
+
927
+ const evmDeployedBytecode = contractOutput.evm?.deployedBytecode;
928
+ let deployedBytecode: string = evmDeployedBytecode?.object ?? "";
929
+
930
+ if (deployedBytecode.slice(0, 2).toLowerCase() !== "0x") {
931
+ deployedBytecode = `0x${deployedBytecode}`;
932
+ }
933
+
934
+ const linkReferences = evmBytecode?.linkReferences ?? {};
935
+ const deployedLinkReferences = evmDeployedBytecode?.linkReferences ?? {};
936
+
937
+ return {
938
+ _format: ARTIFACT_FORMAT_VERSION,
939
+ contractName,
940
+ sourceName,
941
+ abi: contractOutput.abi,
942
+ bytecode,
943
+ deployedBytecode,
944
+ linkReferences,
945
+ deployedLinkReferences,
946
+ };
947
+ }