hardhat 2.6.6 → 2.8.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/builtin-tasks/compile.js +9 -0
  3. package/builtin-tasks/compile.js.map +1 -1
  4. package/builtin-tasks/node.js +26 -9
  5. package/builtin-tasks/node.js.map +1 -1
  6. package/internal/artifacts.d.ts +49 -0
  7. package/internal/artifacts.d.ts.map +1 -1
  8. package/internal/artifacts.js +191 -55
  9. package/internal/artifacts.js.map +1 -1
  10. package/internal/cli/analytics.js +2 -2
  11. package/internal/cli/analytics.js.map +1 -1
  12. package/internal/cli/cli.js +1 -1
  13. package/internal/cli/cli.js.map +1 -1
  14. package/internal/constants.d.ts +2 -0
  15. package/internal/constants.d.ts.map +1 -1
  16. package/internal/constants.js +3 -1
  17. package/internal/constants.js.map +1 -1
  18. package/internal/core/config/config-loading.d.ts.map +1 -1
  19. package/internal/core/config/config-loading.js +16 -2
  20. package/internal/core/config/config-loading.js.map +1 -1
  21. package/internal/core/config/config-resolution.d.ts.map +1 -1
  22. package/internal/core/config/config-resolution.js +42 -4
  23. package/internal/core/config/config-resolution.js.map +1 -1
  24. package/internal/core/config/config-validation.d.ts +1 -0
  25. package/internal/core/config/config-validation.d.ts.map +1 -1
  26. package/internal/core/config/config-validation.js +126 -13
  27. package/internal/core/config/config-validation.js.map +1 -1
  28. package/internal/core/config/default-config.d.ts +1 -0
  29. package/internal/core/config/default-config.d.ts.map +1 -1
  30. package/internal/core/config/default-config.js +69 -4
  31. package/internal/core/config/default-config.js.map +1 -1
  32. package/internal/core/errors-list.d.ts +14 -0
  33. package/internal/core/errors-list.d.ts.map +1 -1
  34. package/internal/core/errors-list.js +21 -2
  35. package/internal/core/errors-list.js.map +1 -1
  36. package/internal/core/jsonrpc/types/output/log.d.ts +1 -0
  37. package/internal/core/jsonrpc/types/output/log.d.ts.map +1 -1
  38. package/internal/core/jsonrpc/types/output/log.js +1 -0
  39. package/internal/core/jsonrpc/types/output/log.js.map +1 -1
  40. package/internal/core/jsonrpc/types/output/receipt.d.ts +1 -0
  41. package/internal/core/jsonrpc/types/output/receipt.d.ts.map +1 -1
  42. package/internal/core/params/hardhat-params.js +2 -2
  43. package/internal/core/params/hardhat-params.js.map +1 -1
  44. package/internal/core/providers/accounts.d.ts.map +1 -1
  45. package/internal/core/providers/accounts.js +14 -0
  46. package/internal/core/providers/accounts.js.map +1 -1
  47. package/internal/core/providers/construction.d.ts.map +1 -1
  48. package/internal/core/providers/construction.js +4 -2
  49. package/internal/core/providers/construction.js.map +1 -1
  50. package/internal/core/providers/gas-providers.d.ts.map +1 -1
  51. package/internal/core/providers/gas-providers.js +1 -1
  52. package/internal/core/providers/gas-providers.js.map +1 -1
  53. package/internal/core/typescript-support.d.ts +1 -1
  54. package/internal/core/typescript-support.d.ts.map +1 -1
  55. package/internal/core/typescript-support.js +4 -1
  56. package/internal/core/typescript-support.js.map +1 -1
  57. package/internal/hardhat-network/jsonrpc/client.d.ts +2 -0
  58. package/internal/hardhat-network/jsonrpc/client.d.ts.map +1 -1
  59. package/internal/hardhat-network/provider/BlockchainData.d.ts +1 -1
  60. package/internal/hardhat-network/provider/TransactionQueue.d.ts +2 -1
  61. package/internal/hardhat-network/provider/TransactionQueue.d.ts.map +1 -1
  62. package/internal/hardhat-network/provider/TransactionQueue.js +16 -2
  63. package/internal/hardhat-network/provider/TransactionQueue.js.map +1 -1
  64. package/internal/hardhat-network/provider/fork/ForkBlockchain.d.ts.map +1 -1
  65. package/internal/hardhat-network/provider/fork/ForkBlockchain.js +1 -3
  66. package/internal/hardhat-network/provider/fork/ForkBlockchain.js.map +1 -1
  67. package/internal/hardhat-network/provider/modules/hardhat.d.ts +3 -0
  68. package/internal/hardhat-network/provider/modules/hardhat.d.ts.map +1 -1
  69. package/internal/hardhat-network/provider/modules/hardhat.js +16 -0
  70. package/internal/hardhat-network/provider/modules/hardhat.js.map +1 -1
  71. package/internal/hardhat-network/provider/modules/personal.d.ts +9 -0
  72. package/internal/hardhat-network/provider/modules/personal.d.ts.map +1 -0
  73. package/internal/hardhat-network/provider/modules/personal.js +31 -0
  74. package/internal/hardhat-network/provider/modules/personal.js.map +1 -0
  75. package/internal/hardhat-network/provider/node-types.d.ts +7 -1
  76. package/internal/hardhat-network/provider/node-types.d.ts.map +1 -1
  77. package/internal/hardhat-network/provider/node-types.js.map +1 -1
  78. package/internal/hardhat-network/provider/node.d.ts +11 -2
  79. package/internal/hardhat-network/provider/node.d.ts.map +1 -1
  80. package/internal/hardhat-network/provider/node.js +108 -31
  81. package/internal/hardhat-network/provider/node.js.map +1 -1
  82. package/internal/hardhat-network/provider/output.d.ts +1 -1
  83. package/internal/hardhat-network/provider/output.d.ts.map +1 -1
  84. package/internal/hardhat-network/provider/output.js +9 -6
  85. package/internal/hardhat-network/provider/output.js.map +1 -1
  86. package/internal/hardhat-network/provider/provider.d.ts +8 -3
  87. package/internal/hardhat-network/provider/provider.d.ts.map +1 -1
  88. package/internal/hardhat-network/provider/provider.js +14 -2
  89. package/internal/hardhat-network/provider/provider.js.map +1 -1
  90. package/internal/hardhat-network/stack-traces/error-inferrer.d.ts.map +1 -1
  91. package/internal/hardhat-network/stack-traces/error-inferrer.js +14 -0
  92. package/internal/hardhat-network/stack-traces/error-inferrer.js.map +1 -1
  93. package/internal/hardhat-network/stack-traces/solidityTracer.d.ts +1 -1
  94. package/internal/hardhat-network/stack-traces/solidityTracer.js +1 -1
  95. package/package.json +5 -5
  96. package/register.js +1 -1
  97. package/register.js.map +1 -1
  98. package/src/builtin-tasks/compile.ts +14 -0
  99. package/src/builtin-tasks/node.ts +41 -9
  100. package/src/internal/artifacts.ts +268 -71
  101. package/src/internal/cli/analytics.ts +1 -1
  102. package/src/internal/cli/cli.ts +1 -1
  103. package/src/internal/constants.ts +3 -0
  104. package/src/internal/core/config/config-loading.ts +24 -2
  105. package/src/internal/core/config/config-resolution.ts +61 -3
  106. package/src/internal/core/config/config-validation.ts +217 -15
  107. package/src/internal/core/config/default-config.ts +67 -2
  108. package/src/internal/core/errors-list.ts +21 -2
  109. package/src/internal/core/jsonrpc/types/output/log.ts +1 -0
  110. package/src/internal/core/params/hardhat-params.ts +2 -2
  111. package/src/internal/core/providers/accounts.ts +19 -0
  112. package/src/internal/core/providers/construction.ts +9 -2
  113. package/src/internal/core/providers/gas-providers.ts +1 -1
  114. package/src/internal/core/typescript-support.ts +5 -1
  115. package/src/internal/hardhat-network/provider/TransactionQueue.ts +31 -4
  116. package/src/internal/hardhat-network/provider/fork/ForkBlockchain.ts +1 -3
  117. package/src/internal/hardhat-network/provider/modules/hardhat.ts +23 -0
  118. package/src/internal/hardhat-network/provider/modules/personal.ts +39 -0
  119. package/src/internal/hardhat-network/provider/node-types.ts +8 -1
  120. package/src/internal/hardhat-network/provider/node.ts +164 -29
  121. package/src/internal/hardhat-network/provider/output.ts +9 -9
  122. package/src/internal/hardhat-network/provider/provider.ts +18 -1
  123. package/src/internal/hardhat-network/stack-traces/error-inferrer.ts +19 -0
  124. package/src/internal/hardhat-network/stack-traces/solidityTracer.ts +1 -1
  125. package/src/register.ts +1 -1
  126. package/src/types/config.ts +42 -0
  127. package/src/utils/contract-names.ts +112 -0
  128. package/src/utils/source-names.ts +1 -1
  129. package/types/config.d.ts +26 -0
  130. package/types/config.d.ts.map +1 -1
  131. package/utils/contract-names.d.ts +10 -0
  132. package/utils/contract-names.d.ts.map +1 -1
  133. package/utils/contract-names.js +92 -1
  134. package/utils/contract-names.js.map +1 -1
  135. package/utils/source-names.d.ts +1 -1
  136. package/utils/source-names.js +1 -1
@@ -20,6 +20,7 @@ import {
20
20
  JsonRpcServer,
21
21
  } from "../types";
22
22
 
23
+ import { HARDHAT_NETWORK_MNEMONIC } from "../internal/core/config/default-config";
23
24
  import {
24
25
  TASK_NODE,
25
26
  TASK_NODE_CREATE_SERVER,
@@ -31,10 +32,23 @@ import { watchCompilerOutput } from "./utils/watch";
31
32
 
32
33
  const log = debug("hardhat:core:tasks:node");
33
34
 
35
+ function printDefaultConfigWarning() {
36
+ console.log(
37
+ chalk.bold(
38
+ "WARNING: These accounts, and their private keys, are publicly known."
39
+ )
40
+ );
41
+ console.log(
42
+ chalk.bold(
43
+ "Any funds sent to them on Mainnet or any other live network WILL BE LOST."
44
+ )
45
+ );
46
+ }
47
+
34
48
  function logHardhatNetworkAccounts(networkConfig: HardhatNetworkConfig) {
35
- if (networkConfig.accounts === undefined) {
36
- return;
37
- }
49
+ const isDefaultConfig =
50
+ !Array.isArray(networkConfig.accounts) &&
51
+ networkConfig.accounts.mnemonic === HARDHAT_NETWORK_MNEMONIC;
38
52
 
39
53
  const { BN, bufferToHex, privateToAddress, toBuffer } =
40
54
  require("ethereumjs-util") as typeof EthereumjsUtilT;
@@ -42,20 +56,38 @@ function logHardhatNetworkAccounts(networkConfig: HardhatNetworkConfig) {
42
56
  console.log("Accounts");
43
57
  console.log("========");
44
58
 
59
+ if (isDefaultConfig) {
60
+ console.log();
61
+ printDefaultConfigWarning();
62
+ console.log();
63
+ }
64
+
45
65
  const accounts = normalizeHardhatNetworkAccountsConfig(
46
66
  networkConfig.accounts
47
67
  );
48
68
 
49
69
  for (const [index, account] of accounts.entries()) {
50
70
  const address = bufferToHex(privateToAddress(toBuffer(account.privateKey)));
51
- const privateKey = bufferToHex(toBuffer(account.privateKey));
71
+
52
72
  const balance = new BN(account.balance)
53
73
  .div(new BN(10).pow(new BN(18)))
54
74
  .toString(10);
55
75
 
56
- console.log(`Account #${index}: ${address} (${balance} ETH)
57
- Private Key: ${privateKey}
58
- `);
76
+ let entry = `Account #${index}: ${address} (${balance} ETH)`;
77
+
78
+ if (isDefaultConfig) {
79
+ const privateKey = bufferToHex(toBuffer(account.privateKey));
80
+ entry += `
81
+ Private Key: ${privateKey}`;
82
+ }
83
+
84
+ console.log(entry);
85
+ console.log();
86
+ }
87
+
88
+ if (isDefaultConfig) {
89
+ printDefaultConfigWarning();
90
+ console.log();
59
91
  }
60
92
  }
61
93
 
@@ -268,7 +300,7 @@ task(TASK_NODE, "Starts a JSON-RPC server on top of Hardhat Network")
268
300
  forkUrl,
269
301
  });
270
302
 
271
- // the default hostname is "localhost" unless we are inside a docker
303
+ // the default hostname is "127.0.0.1" unless we are inside a docker
272
304
  // container, in that case we use "0.0.0.0"
273
305
  let hostname: string;
274
306
  if (hostnameParam !== undefined) {
@@ -278,7 +310,7 @@ task(TASK_NODE, "Starts a JSON-RPC server on top of Hardhat Network")
278
310
  if (insideDocker) {
279
311
  hostname = "0.0.0.0";
280
312
  } else {
281
- hostname = "localhost";
313
+ hostname = "127.0.0.1";
282
314
  }
283
315
  }
284
316
 
@@ -15,6 +15,7 @@ import {
15
15
  getFullyQualifiedName,
16
16
  isFullyQualifiedName,
17
17
  parseFullyQualifiedName,
18
+ findDistance,
18
19
  } from "../utils/contract-names";
19
20
  import { replaceBackslashes } from "../utils/source-names";
20
21
 
@@ -23,6 +24,7 @@ import {
23
24
  BUILD_INFO_DIR_NAME,
24
25
  BUILD_INFO_FORMAT_VERSION,
25
26
  DEBUG_FILE_FORMAT_VERSION,
27
+ EDIT_DISTANCE_THRESHOLD,
26
28
  } from "./constants";
27
29
  import { HardhatError } from "./core/errors";
28
30
  import { ERRORS } from "./core/errors-list";
@@ -45,71 +47,13 @@ export class Artifacts implements IArtifacts {
45
47
  }
46
48
 
47
49
  public async readArtifact(name: string): Promise<Artifact> {
48
- const { trueCasePath } = await import("true-case-path");
49
50
  const artifactPath = await this._getArtifactPath(name);
50
-
51
- try {
52
- const trueCaseArtifactPath = await trueCasePath(
53
- path.relative(this._artifactsPath, artifactPath),
54
- this._artifactsPath
55
- );
56
-
57
- if (artifactPath !== trueCaseArtifactPath) {
58
- throw new HardhatError(ERRORS.ARTIFACTS.WRONG_CASING, {
59
- correct: trueCaseArtifactPath,
60
- incorrect: artifactPath,
61
- });
62
- }
63
-
64
- return await fsExtra.readJson(trueCaseArtifactPath);
65
- } catch (error) {
66
- if (
67
- typeof error.message === "string" &&
68
- error.message.includes("no matching file exists")
69
- ) {
70
- throw new HardhatError(ERRORS.INTERNAL.WRONG_ARTIFACT_PATH, {
71
- contractName: name,
72
- artifactPath,
73
- });
74
- }
75
-
76
- // eslint-disable-next-line @nomiclabs/hardhat-internal-rules/only-hardhat-error
77
- throw error;
78
- }
51
+ return fsExtra.readJson(artifactPath);
79
52
  }
80
53
 
81
54
  public readArtifactSync(name: string): Artifact {
82
- const { trueCasePathSync } = require("true-case-path");
83
55
  const artifactPath = this._getArtifactPathSync(name);
84
-
85
- try {
86
- const trueCaseArtifactPath = trueCasePathSync(
87
- path.relative(this._artifactsPath, artifactPath),
88
- this._artifactsPath
89
- );
90
-
91
- if (artifactPath !== trueCaseArtifactPath) {
92
- throw new HardhatError(ERRORS.ARTIFACTS.WRONG_CASING, {
93
- correct: trueCaseArtifactPath,
94
- incorrect: artifactPath,
95
- });
96
- }
97
-
98
- return fsExtra.readJsonSync(trueCaseArtifactPath);
99
- } catch (error) {
100
- if (
101
- typeof error.message === "string" &&
102
- error.message.includes("no matching file exists")
103
- ) {
104
- throw new HardhatError(ERRORS.INTERNAL.WRONG_ARTIFACT_PATH, {
105
- contractName: name,
106
- artifactPath,
107
- });
108
- }
109
-
110
- // eslint-disable-next-line @nomiclabs/hardhat-internal-rules/only-hardhat-error
111
- throw error;
112
- }
56
+ return fsExtra.readJsonSync(artifactPath);
113
57
  }
114
58
 
115
59
  public async artifactExists(name: string): Promise<boolean> {
@@ -130,7 +74,7 @@ export class Artifacts implements IArtifacts {
130
74
  fullyQualifiedName: string
131
75
  ): Promise<BuildInfo | undefined> {
132
76
  const artifactPath =
133
- this._getArtifactPathFromFullyQualifiedName(fullyQualifiedName);
77
+ this.formArtifactPathFromFullyQualifiedName(fullyQualifiedName);
134
78
 
135
79
  const debugFilePath = this._getDebugFilePath(artifactPath);
136
80
  const buildInfoPath = await this._getBuildInfoFromDebugFile(debugFilePath);
@@ -173,7 +117,7 @@ export class Artifacts implements IArtifacts {
173
117
  );
174
118
 
175
119
  const artifactPath =
176
- this._getArtifactPathFromFullyQualifiedName(fullyQualifiedName);
120
+ this.formArtifactPathFromFullyQualifiedName(fullyQualifiedName);
177
121
 
178
122
  await fsExtra.ensureDir(path.dirname(artifactPath));
179
123
 
@@ -280,6 +224,18 @@ export class Artifacts implements IArtifacts {
280
224
  }
281
225
  }
282
226
 
227
+ /**
228
+ * Returns the absolute path to the given artifact
229
+ */
230
+ public formArtifactPathFromFullyQualifiedName(
231
+ fullyQualifiedName: string
232
+ ): string {
233
+ const { sourceName, contractName } =
234
+ parseFullyQualifiedName(fullyQualifiedName);
235
+
236
+ return path.join(this._artifactsPath, sourceName, `${contractName}.json`);
237
+ }
238
+
283
239
  private _getBuildInfoName(
284
240
  solcVersion: string,
285
241
  solcLongVersion: string,
@@ -307,7 +263,7 @@ export class Artifacts implements IArtifacts {
307
263
  */
308
264
  private async _getArtifactPath(name: string): Promise<string> {
309
265
  if (isFullyQualifiedName(name)) {
310
- return this._getArtifactPathFromFullyQualifiedName(name);
266
+ return this._getValidArtifactPathFromFullyQualifiedName(name);
311
267
  }
312
268
 
313
269
  const files = await this.getArtifactPaths();
@@ -346,9 +302,11 @@ export class Artifacts implements IArtifacts {
346
302
  }
347
303
 
348
304
  private _getArtifactPathsSync(): string[] {
349
- return globSync(path.join(this._artifactsPath, "**/*.json"), {
305
+ const paths = globSync(path.join(this._artifactsPath, "**/*.json"), {
350
306
  ignore: [this._buildInfosGlob, this._dbgsGlob],
351
307
  });
308
+
309
+ return paths.sort();
352
310
  }
353
311
 
354
312
  /**
@@ -356,13 +314,69 @@ export class Artifacts implements IArtifacts {
356
314
  */
357
315
  private _getArtifactPathSync(name: string): string {
358
316
  if (isFullyQualifiedName(name)) {
359
- return this._getArtifactPathFromFullyQualifiedName(name);
317
+ return this._getValidArtifactPathFromFullyQualifiedNameSync(name);
360
318
  }
361
319
 
362
320
  const files = this._getArtifactPathsSync();
363
321
  return this._getArtifactPathFromFiles(name, files);
364
322
  }
365
323
 
324
+ /**
325
+ * Same signature as imported function, but abstracted to handle the only error we consistently care about
326
+ */
327
+ private async _trueCasePath(
328
+ filePath: string,
329
+ basePath?: string
330
+ ): Promise<string | null> {
331
+ const { trueCasePath } = await import("true-case-path");
332
+
333
+ try {
334
+ const result = await trueCasePath(filePath, basePath);
335
+ return result;
336
+ } catch (error: unknown) {
337
+ if (error instanceof Error) {
338
+ if (error.message.includes("no matching file exists")) {
339
+ return null;
340
+ }
341
+ }
342
+
343
+ // eslint-disable-next-line @nomiclabs/hardhat-internal-rules/only-hardhat-error
344
+ throw error;
345
+ }
346
+ }
347
+
348
+ /**
349
+ * Same signature as imported function, but abstracted to handle the only error we consistently care about
350
+ * and synchronous
351
+ */
352
+ private _trueCasePathSync(
353
+ filePath: string,
354
+ basePath?: string
355
+ ): string | null {
356
+ const { trueCasePathSync } = require("true-case-path");
357
+
358
+ try {
359
+ const result = trueCasePathSync(filePath, basePath);
360
+ return result;
361
+ } catch (error: unknown) {
362
+ if (error instanceof Error) {
363
+ if (error.message.includes("no matching file exists")) {
364
+ return null;
365
+ }
366
+ }
367
+
368
+ // eslint-disable-next-line @nomiclabs/hardhat-internal-rules/only-hardhat-error
369
+ throw error;
370
+ }
371
+ }
372
+
373
+ /**
374
+ * DO NOT DELETE OR CHANGE
375
+ *
376
+ * use this.formArtifactPathFromFullyQualifiedName instead
377
+ * @deprecated until typechain migrates to public version
378
+ * @see https://github.com/dethcrypto/TypeChain/issues/544
379
+ */
366
380
  private _getArtifactPathFromFullyQualifiedName(
367
381
  fullyQualifiedName: string
368
382
  ): string {
@@ -372,6 +386,191 @@ export class Artifacts implements IArtifacts {
372
386
  return path.join(this._artifactsPath, sourceName, `${contractName}.json`);
373
387
  }
374
388
 
389
+ private async _getValidArtifactPathFromFullyQualifiedName(
390
+ fullyQualifiedName: string
391
+ ): Promise<string> {
392
+ const artifactPath =
393
+ this.formArtifactPathFromFullyQualifiedName(fullyQualifiedName);
394
+
395
+ const trueCaseArtifactPath = await this._trueCasePath(
396
+ path.relative(this._artifactsPath, artifactPath),
397
+ this._artifactsPath
398
+ );
399
+
400
+ if (trueCaseArtifactPath === null) {
401
+ return this._handleWrongArtifactForFullyQualifiedName(fullyQualifiedName);
402
+ }
403
+
404
+ if (artifactPath !== trueCaseArtifactPath) {
405
+ throw new HardhatError(ERRORS.ARTIFACTS.WRONG_CASING, {
406
+ correct: trueCaseArtifactPath,
407
+ incorrect: artifactPath,
408
+ });
409
+ }
410
+
411
+ return artifactPath;
412
+ }
413
+
414
+ private _getAllContractNamesFromFiles(files: string[]): string[] {
415
+ return files.map((file) => {
416
+ const fqn = this._getFullyQualifiedNameFromPath(file);
417
+ return parseFullyQualifiedName(fqn).contractName;
418
+ });
419
+ }
420
+
421
+ private _getAllFullyQualifiedNamesSync(): string[] {
422
+ const paths = this._getArtifactPathsSync();
423
+ return paths.map((p) => this._getFullyQualifiedNameFromPath(p)).sort();
424
+ }
425
+
426
+ private _formatSuggestions(names: string[], contractName?: string): string {
427
+ switch (names.length) {
428
+ case 0:
429
+ return "";
430
+ case 1:
431
+ return `Did you mean "${names[0]}"?`;
432
+ default:
433
+ return `We found some that were similar:
434
+
435
+ ${names.map((n) => ` * ${n}`).join(os.EOL)}
436
+
437
+ Please replace "${contractName}" for the correct contract name wherever you are trying to read its artifact.
438
+ `;
439
+ }
440
+ }
441
+
442
+ private _handleWrongArtifactForFullyQualifiedName(
443
+ fullyQualifiedName: string
444
+ ): never {
445
+ const names = this._getAllFullyQualifiedNamesSync();
446
+
447
+ const similarNames = this._getSimilarContractNames(
448
+ fullyQualifiedName,
449
+ names
450
+ );
451
+
452
+ throw new HardhatError(ERRORS.ARTIFACTS.NOT_FOUND, {
453
+ contractName: fullyQualifiedName,
454
+ suggestion: this._formatSuggestions(similarNames),
455
+ });
456
+ }
457
+
458
+ private _handleWrongArtifactForContractName(
459
+ contractName: string,
460
+ files: string[]
461
+ ): never {
462
+ const names = this._getAllContractNamesFromFiles(files);
463
+
464
+ let similarNames = this._getSimilarContractNames(contractName, names);
465
+
466
+ if (similarNames.length > 1) {
467
+ similarNames = this._filterDuplicatesAsFullyQualifiedNames(
468
+ files,
469
+ similarNames
470
+ );
471
+ }
472
+
473
+ throw new HardhatError(ERRORS.ARTIFACTS.NOT_FOUND, {
474
+ contractName,
475
+ suggestion: this._formatSuggestions(similarNames, contractName),
476
+ });
477
+ }
478
+
479
+ /**
480
+ * If the project has these contracts:
481
+ * - 'contracts/Greeter.sol:Greeter'
482
+ * - 'contracts/Meeter.sol:Greeter'
483
+ * - 'contracts/Greater.sol:Greater'
484
+ * And the user tries to get an artifact with the name 'Greter', then
485
+ * the suggestions will be 'Greeter', 'Greeter', and 'Greater'.
486
+ *
487
+ * We don't want to show duplicates here, so we use FQNs for those. The
488
+ * suggestions will then be:
489
+ * - 'contracts/Greeter.sol:Greeter'
490
+ * - 'contracts/Meeter.sol:Greeter'
491
+ * - 'Greater'
492
+ */
493
+ private _filterDuplicatesAsFullyQualifiedNames(
494
+ files: string[],
495
+ similarNames: string[]
496
+ ): string[] {
497
+ const outputNames = [];
498
+ const groups = similarNames.reduce((obj, cur) => {
499
+ obj[cur] = obj[cur] ? obj[cur] + 1 : 1;
500
+ return obj;
501
+ }, {} as { [k: string]: number });
502
+
503
+ for (const [name, occurrences] of Object.entries(groups)) {
504
+ if (occurrences > 1) {
505
+ for (const file of files) {
506
+ if (path.basename(file) === `${name}.json`) {
507
+ outputNames.push(this._getFullyQualifiedNameFromPath(file));
508
+ }
509
+ }
510
+ continue;
511
+ }
512
+
513
+ outputNames.push(name);
514
+ }
515
+
516
+ return outputNames;
517
+ }
518
+
519
+ /**
520
+ *
521
+ * @param givenName can be FQN or contract name
522
+ * @param names MUST match type of givenName (i.e. array of FQN's if givenName is FQN)
523
+ * @returns
524
+ */
525
+ private _getSimilarContractNames(
526
+ givenName: string,
527
+ names: string[]
528
+ ): string[] {
529
+ let shortestDistance = EDIT_DISTANCE_THRESHOLD;
530
+ let mostSimilarNames: string[] = [];
531
+ for (const name of names) {
532
+ const distance = findDistance(givenName, name);
533
+
534
+ if (distance < shortestDistance) {
535
+ shortestDistance = distance;
536
+ mostSimilarNames = [name];
537
+ continue;
538
+ }
539
+
540
+ if (distance === shortestDistance) {
541
+ mostSimilarNames.push(name);
542
+ continue;
543
+ }
544
+ }
545
+
546
+ return mostSimilarNames;
547
+ }
548
+
549
+ private _getValidArtifactPathFromFullyQualifiedNameSync(
550
+ fullyQualifiedName: string
551
+ ): string {
552
+ const artifactPath =
553
+ this.formArtifactPathFromFullyQualifiedName(fullyQualifiedName);
554
+
555
+ const trueCaseArtifactPath = this._trueCasePathSync(
556
+ path.relative(this._artifactsPath, artifactPath),
557
+ this._artifactsPath
558
+ );
559
+
560
+ if (trueCaseArtifactPath === null) {
561
+ return this._handleWrongArtifactForFullyQualifiedName(fullyQualifiedName);
562
+ }
563
+
564
+ if (artifactPath !== trueCaseArtifactPath) {
565
+ throw new HardhatError(ERRORS.ARTIFACTS.WRONG_CASING, {
566
+ correct: trueCaseArtifactPath,
567
+ incorrect: artifactPath,
568
+ });
569
+ }
570
+
571
+ return artifactPath;
572
+ }
573
+
375
574
  private _getDebugFilePath(artifactPath: string): string {
376
575
  return artifactPath.replace(/\.json$/, ".dbg.json");
377
576
  }
@@ -385,15 +584,13 @@ export class Artifacts implements IArtifacts {
385
584
  });
386
585
 
387
586
  if (matchingFiles.length === 0) {
388
- throw new HardhatError(ERRORS.ARTIFACTS.NOT_FOUND, {
389
- contractName,
390
- });
587
+ return this._handleWrongArtifactForContractName(contractName, files);
391
588
  }
392
589
 
393
590
  if (matchingFiles.length > 1) {
394
- const candidates = matchingFiles
395
- .map((file) => this._getFullyQualifiedNameFromPath(file))
396
- .map(path.normalize);
591
+ const candidates = matchingFiles.map((file) =>
592
+ this._getFullyQualifiedNameFromPath(file)
593
+ );
397
594
 
398
595
  throw new HardhatError(ERRORS.ARTIFACTS.MULTIPLE_FOUND, {
399
596
  contractName,
@@ -3,7 +3,7 @@ import debug from "debug";
3
3
  import fetch from "node-fetch";
4
4
  import os from "os";
5
5
  import qs from "qs";
6
- import uuid from "uuid/v4";
6
+ import { v4 as uuid } from "uuid";
7
7
 
8
8
  import * as builtinTaskNames from "../../builtin-tasks/task-names";
9
9
  import { isLocalDev } from "../core/execution-mode";
@@ -121,7 +121,7 @@ async function main() {
121
121
  }
122
122
 
123
123
  if (willRunWithTypescript(hardhatArguments.config)) {
124
- loadTsNode();
124
+ loadTsNode(hardhatArguments.tsconfig);
125
125
  }
126
126
 
127
127
  let taskName = parsedTaskName ?? TASK_HELP;
@@ -20,10 +20,13 @@ export const HARDHAT_NETWORK_SUPPORTED_HARDFORKS = [
20
20
  "london",
21
21
  ];
22
22
 
23
+ export const HARDHAT_MEMPOOL_SUPPORTED_ORDERS = <const>["fifo", "priority"];
24
+
23
25
  export const ARTIFACT_FORMAT_VERSION = "hh-sol-artifact-1";
24
26
  export const DEBUG_FILE_FORMAT_VERSION = "hh-sol-dbg-1";
25
27
  export const BUILD_INFO_FORMAT_VERSION = "hh-sol-build-info-1";
26
28
  export const BUILD_INFO_DIR_NAME = "build-info";
29
+ export const EDIT_DISTANCE_THRESHOLD = 3;
27
30
 
28
31
  export const HARDHAT_NETWORK_RESET_EVENT = "hardhatNetworkReset";
29
32
  export const HARDHAT_NETWORK_REVERT_SNAPSHOT_EVENT =
@@ -92,6 +92,7 @@ export function loadConfigAndTasks(
92
92
 
93
93
  if (showSolidityConfigWarnings) {
94
94
  checkUnsupportedSolidityConfig(resolved);
95
+ checkUnsupportedRemappings(resolved);
95
96
  }
96
97
 
97
98
  return resolved;
@@ -223,7 +224,7 @@ function checkMissingSolidityConfig(userConfig: any) {
223
224
  if (userConfig.solidity === undefined) {
224
225
  console.warn(
225
226
  chalk.yellow(
226
- `Solidity compiler is not configured. Version ${DEFAULT_SOLC_VERSION} will be used by default. Add a 'solidity' entry to your configuration to supress this warning.
227
+ `Solidity compiler is not configured. Version ${DEFAULT_SOLC_VERSION} will be used by default. Add a 'solidity' entry to your configuration to suppress this warning.
227
228
 
228
229
  Learn more about compiler configuration at https://hardhat.org/config"
229
230
  `
@@ -255,7 +256,28 @@ function checkUnsupportedSolidityConfig(resolvedConfig: HardhatConfig) {
255
256
  unsupportedVersions.length === 1 ? "is" : "are"
256
257
  } not fully supported yet. You can still use Hardhat, but some features, like stack traces, might not work correctly.
257
258
 
258
- Learn more at https://hardhat.org/reference/solidity-support"
259
+ Learn more at https://hardhat.org/reference/solidity-support
260
+ `
261
+ )
262
+ );
263
+ }
264
+ }
265
+
266
+ function checkUnsupportedRemappings({ solidity }: HardhatConfig) {
267
+ const solcConfigs = [
268
+ ...solidity.compilers,
269
+ ...Object.values(solidity.overrides),
270
+ ];
271
+ const remappings = solcConfigs.filter(
272
+ ({ settings }) => settings.remappings !== undefined
273
+ );
274
+
275
+ if (remappings.length > 0) {
276
+ console.warn(
277
+ chalk.yellow(
278
+ `Solidity remappings are not currently supported; you may experience unexpected compilation results. Remove any 'remappings' fields from your configuration to suppress this warning.
279
+
280
+ Learn more about compiler configuration at https://hardhat.org/config
259
281
  `
260
282
  )
261
283
  );