hardhat 2.6.8 → 2.7.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 (108) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/builtin-tasks/node.js +2 -2
  3. package/internal/artifacts.d.ts +49 -0
  4. package/internal/artifacts.d.ts.map +1 -1
  5. package/internal/artifacts.js +191 -55
  6. package/internal/artifacts.js.map +1 -1
  7. package/internal/cli/analytics.js +2 -2
  8. package/internal/cli/analytics.js.map +1 -1
  9. package/internal/cli/cli.js +1 -1
  10. package/internal/cli/cli.js.map +1 -1
  11. package/internal/constants.d.ts +2 -0
  12. package/internal/constants.d.ts.map +1 -1
  13. package/internal/constants.js +3 -1
  14. package/internal/constants.js.map +1 -1
  15. package/internal/core/config/config-loading.d.ts.map +1 -1
  16. package/internal/core/config/config-loading.js +15 -1
  17. package/internal/core/config/config-loading.js.map +1 -1
  18. package/internal/core/config/config-resolution.d.ts.map +1 -1
  19. package/internal/core/config/config-resolution.js +21 -0
  20. package/internal/core/config/config-resolution.js.map +1 -1
  21. package/internal/core/config/config-validation.d.ts +1 -0
  22. package/internal/core/config/config-validation.d.ts.map +1 -1
  23. package/internal/core/config/config-validation.js +88 -13
  24. package/internal/core/config/config-validation.js.map +1 -1
  25. package/internal/core/config/default-config.d.ts.map +1 -1
  26. package/internal/core/config/default-config.js +7 -1
  27. package/internal/core/config/default-config.js.map +1 -1
  28. package/internal/core/errors-list.js +2 -2
  29. package/internal/core/errors-list.js.map +1 -1
  30. package/internal/core/jsonrpc/types/output/log.d.ts +1 -0
  31. package/internal/core/jsonrpc/types/output/log.d.ts.map +1 -1
  32. package/internal/core/jsonrpc/types/output/log.js +1 -0
  33. package/internal/core/jsonrpc/types/output/log.js.map +1 -1
  34. package/internal/core/jsonrpc/types/output/receipt.d.ts +1 -0
  35. package/internal/core/jsonrpc/types/output/receipt.d.ts.map +1 -1
  36. package/internal/core/params/hardhat-params.js +2 -2
  37. package/internal/core/params/hardhat-params.js.map +1 -1
  38. package/internal/core/providers/construction.d.ts.map +1 -1
  39. package/internal/core/providers/construction.js +4 -2
  40. package/internal/core/providers/construction.js.map +1 -1
  41. package/internal/core/typescript-support.d.ts +1 -1
  42. package/internal/core/typescript-support.d.ts.map +1 -1
  43. package/internal/core/typescript-support.js +4 -1
  44. package/internal/core/typescript-support.js.map +1 -1
  45. package/internal/hardhat-network/jsonrpc/client.d.ts +2 -0
  46. package/internal/hardhat-network/jsonrpc/client.d.ts.map +1 -1
  47. package/internal/hardhat-network/provider/TransactionQueue.d.ts +2 -1
  48. package/internal/hardhat-network/provider/TransactionQueue.d.ts.map +1 -1
  49. package/internal/hardhat-network/provider/TransactionQueue.js +16 -2
  50. package/internal/hardhat-network/provider/TransactionQueue.js.map +1 -1
  51. package/internal/hardhat-network/provider/fork/ForkBlockchain.d.ts.map +1 -1
  52. package/internal/hardhat-network/provider/fork/ForkBlockchain.js +1 -3
  53. package/internal/hardhat-network/provider/fork/ForkBlockchain.js.map +1 -1
  54. package/internal/hardhat-network/provider/modules/hardhat.d.ts +2 -0
  55. package/internal/hardhat-network/provider/modules/hardhat.d.ts.map +1 -1
  56. package/internal/hardhat-network/provider/modules/hardhat.js +10 -0
  57. package/internal/hardhat-network/provider/modules/hardhat.js.map +1 -1
  58. package/internal/hardhat-network/provider/node-types.d.ts +5 -0
  59. package/internal/hardhat-network/provider/node-types.d.ts.map +1 -1
  60. package/internal/hardhat-network/provider/node-types.js.map +1 -1
  61. package/internal/hardhat-network/provider/node.d.ts +3 -1
  62. package/internal/hardhat-network/provider/node.d.ts.map +1 -1
  63. package/internal/hardhat-network/provider/node.js +13 -7
  64. package/internal/hardhat-network/provider/node.js.map +1 -1
  65. package/internal/hardhat-network/provider/output.d.ts +1 -1
  66. package/internal/hardhat-network/provider/output.d.ts.map +1 -1
  67. package/internal/hardhat-network/provider/output.js +9 -6
  68. package/internal/hardhat-network/provider/output.js.map +1 -1
  69. package/internal/hardhat-network/provider/provider.d.ts +5 -2
  70. package/internal/hardhat-network/provider/provider.d.ts.map +1 -1
  71. package/internal/hardhat-network/provider/provider.js +7 -2
  72. package/internal/hardhat-network/provider/provider.js.map +1 -1
  73. package/package.json +4 -4
  74. package/register.js +1 -1
  75. package/register.js.map +1 -1
  76. package/src/builtin-tasks/node.ts +2 -2
  77. package/src/internal/artifacts.ts +268 -71
  78. package/src/internal/cli/analytics.ts +1 -1
  79. package/src/internal/cli/cli.ts +1 -1
  80. package/src/internal/constants.ts +3 -0
  81. package/src/internal/core/config/config-loading.ts +23 -1
  82. package/src/internal/core/config/config-resolution.ts +28 -0
  83. package/src/internal/core/config/config-validation.ts +147 -15
  84. package/src/internal/core/config/default-config.ts +7 -1
  85. package/src/internal/core/errors-list.ts +2 -2
  86. package/src/internal/core/jsonrpc/types/output/log.ts +1 -0
  87. package/src/internal/core/params/hardhat-params.ts +2 -2
  88. package/src/internal/core/providers/construction.ts +8 -2
  89. package/src/internal/core/typescript-support.ts +5 -1
  90. package/src/internal/hardhat-network/provider/TransactionQueue.ts +31 -4
  91. package/src/internal/hardhat-network/provider/fork/ForkBlockchain.ts +1 -3
  92. package/src/internal/hardhat-network/provider/modules/hardhat.ts +14 -0
  93. package/src/internal/hardhat-network/provider/node-types.ts +6 -0
  94. package/src/internal/hardhat-network/provider/node.ts +15 -5
  95. package/src/internal/hardhat-network/provider/output.ts +9 -9
  96. package/src/internal/hardhat-network/provider/provider.ts +8 -1
  97. package/src/register.ts +1 -1
  98. package/src/types/config.ts +14 -0
  99. package/src/utils/contract-names.ts +112 -0
  100. package/src/utils/source-names.ts +1 -1
  101. package/types/config.d.ts +10 -0
  102. package/types/config.d.ts.map +1 -1
  103. package/utils/contract-names.d.ts +10 -0
  104. package/utils/contract-names.d.ts.map +1 -1
  105. package/utils/contract-names.js +92 -1
  106. package/utils/contract-names.js.map +1 -1
  107. package/utils/source-names.d.ts +1 -1
  108. package/utils/source-names.js +1 -1
@@ -3,6 +3,7 @@ import { Context, getFunctionName, ValidationError } from "io-ts/lib";
3
3
  import { Reporter } from "io-ts/lib/Reporter";
4
4
 
5
5
  import {
6
+ HARDHAT_MEMPOOL_SUPPORTED_ORDERS,
6
7
  HARDHAT_NETWORK_NAME,
7
8
  HARDHAT_NETWORK_SUPPORTED_HARDFORKS,
8
9
  } from "../../constants";
@@ -53,6 +54,59 @@ function getErrorMessage(path: string, value: any, expectedType: string) {
53
54
  )} for ${path} - Expected a value of type ${expectedType}.`;
54
55
  }
55
56
 
57
+ function getPrivateKeyError(index: number, network: string, message: string) {
58
+ return `Invalid account: #${index} for network: ${network} - ${message}`;
59
+ }
60
+
61
+ function validatePrivateKey(
62
+ privateKey: unknown,
63
+ index: number,
64
+ network: string,
65
+ errors: string[]
66
+ ) {
67
+ if (typeof privateKey !== "string") {
68
+ errors.push(
69
+ getPrivateKeyError(
70
+ index,
71
+ network,
72
+ `Expected string, received ${typeof privateKey}`
73
+ )
74
+ );
75
+ } else {
76
+ // private key validation
77
+ const pkWithPrefix = /^0x/.test(privateKey)
78
+ ? privateKey
79
+ : `0x${privateKey}`;
80
+
81
+ // 32 bytes = 64 characters + 2 char prefix = 66
82
+ if (pkWithPrefix.length < 66) {
83
+ errors.push(
84
+ getPrivateKeyError(
85
+ index,
86
+ network,
87
+ "private key too short, expected 32 bytes"
88
+ )
89
+ );
90
+ } else if (pkWithPrefix.length > 66) {
91
+ errors.push(
92
+ getPrivateKeyError(
93
+ index,
94
+ network,
95
+ "private key too long, expected 32 bytes"
96
+ )
97
+ );
98
+ } else if (hexString.decode(pkWithPrefix).isLeft()) {
99
+ errors.push(
100
+ getPrivateKeyError(
101
+ index,
102
+ network,
103
+ "invalid hex character(s) found in string"
104
+ )
105
+ );
106
+ }
107
+ }
108
+ }
109
+
56
110
  export function failure(es: ValidationError[]): string[] {
57
111
  return es.map(getMessage);
58
112
  }
@@ -91,6 +145,27 @@ export const hexString = new t.Type<string>(
91
145
  t.identity
92
146
  );
93
147
 
148
+ function isAddress(v: unknown): v is string {
149
+ if (typeof v !== "string") {
150
+ return false;
151
+ }
152
+
153
+ const trimmed = v.trim();
154
+
155
+ return (
156
+ trimmed.match(HEX_STRING_REGEX) !== null &&
157
+ trimmed.startsWith("0x") &&
158
+ trimmed.length === 42
159
+ );
160
+ }
161
+
162
+ export const address = new t.Type<string>(
163
+ "address",
164
+ isAddress,
165
+ (u, c) => (isAddress(u) ? t.success(u) : t.failure(u, c)),
166
+ t.identity
167
+ );
168
+
94
169
  export const decimalString = new t.Type<string>(
95
170
  "decimal string",
96
171
  isDecimalString,
@@ -123,6 +198,22 @@ const HardhatNetworkForkingConfig = t.type({
123
198
  blockNumber: optional(t.number),
124
199
  });
125
200
 
201
+ const HardhatNetworkMempoolConfig = t.type({
202
+ order: optional(
203
+ t.keyof(
204
+ fromEntries(
205
+ HARDHAT_MEMPOOL_SUPPORTED_ORDERS.map((order) => [order, null])
206
+ )
207
+ )
208
+ ),
209
+ });
210
+
211
+ const HardhatNetworkMiningConfig = t.type({
212
+ auto: optional(t.boolean),
213
+ interval: optional(t.union([t.number, t.tuple([t.number, t.number])])),
214
+ mempool: optional(HardhatNetworkMempoolConfig),
215
+ });
216
+
126
217
  const commonNetworkConfigFields = {
127
218
  chainId: optional(t.number),
128
219
  from: optional(t.string),
@@ -149,6 +240,8 @@ const HardhatNetworkConfig = t.type({
149
240
  initialDate: optional(t.string),
150
241
  loggingEnabled: optional(t.boolean),
151
242
  forking: optional(HardhatNetworkForkingConfig),
243
+ mining: optional(HardhatNetworkMiningConfig),
244
+ coinbase: optional(address),
152
245
  });
153
246
 
154
247
  const HDAccountsConfig = t.type({
@@ -224,7 +317,7 @@ export function validateConfig(config: any) {
224
317
  }
225
318
 
226
319
  export function getValidationErrors(config: any): string[] {
227
- const errors = [];
320
+ const errors: string[] = [];
228
321
 
229
322
  // These can't be validated with io-ts
230
323
  if (config !== undefined && typeof config.networks === "object") {
@@ -237,8 +330,7 @@ export function getValidationErrors(config: any): string[] {
237
330
  }
238
331
 
239
332
  // Validating the accounts with io-ts leads to very confusing errors messages
240
- const configExceptAccounts = { ...hardhatNetwork };
241
- delete configExceptAccounts.accounts;
333
+ const { accounts, ...configExceptAccounts } = hardhatNetwork;
242
334
 
243
335
  const netConfigResult = HardhatNetworkConfig.decode(configExceptAccounts);
244
336
  if (netConfigResult.isLeft()) {
@@ -251,31 +343,37 @@ export function getValidationErrors(config: any): string[] {
251
343
  );
252
344
  }
253
345
 
254
- if (Array.isArray(hardhatNetwork.accounts)) {
255
- for (const account of hardhatNetwork.accounts) {
256
- if (typeof account.privateKey !== "string") {
346
+ // manual validation of accounts
347
+ if (Array.isArray(accounts)) {
348
+ for (const [index, account] of accounts.entries()) {
349
+ if (typeof account !== "object") {
257
350
  errors.push(
258
- getErrorMessage(
259
- `HardhatConfig.networks.${HARDHAT_NETWORK_NAME}.accounts[].privateKey`,
260
- account.privateKey,
261
- "string"
351
+ getPrivateKeyError(
352
+ index,
353
+ HARDHAT_NETWORK_NAME,
354
+ `Expected object, received ${typeof account}`
262
355
  )
263
356
  );
357
+ continue;
264
358
  }
265
359
 
266
- if (typeof account.balance !== "string") {
360
+ const { privateKey, balance } = account;
361
+
362
+ validatePrivateKey(privateKey, index, HARDHAT_NETWORK_NAME, errors);
363
+
364
+ if (typeof balance !== "string") {
267
365
  errors.push(
268
366
  getErrorMessage(
269
367
  `HardhatConfig.networks.${HARDHAT_NETWORK_NAME}.accounts[].balance`,
270
- account.balance,
368
+ balance,
271
369
  "string"
272
370
  )
273
371
  );
274
- } else if (decimalString.decode(account.balance).isLeft()) {
372
+ } else if (decimalString.decode(balance).isLeft()) {
275
373
  errors.push(
276
374
  getErrorMessage(
277
375
  `HardhatConfig.networks.${HARDHAT_NETWORK_NAME}.accounts[].balance`,
278
- account.balance,
376
+ balance,
279
377
  "decimal(wei)"
280
378
  )
281
379
  );
@@ -340,7 +438,9 @@ export function getValidationErrors(config: any): string[] {
340
438
  }
341
439
  }
342
440
 
343
- const netConfigResult = HttpNetworkConfig.decode(netConfig);
441
+ const { accounts, ...configExceptAccounts } = netConfig;
442
+
443
+ const netConfigResult = HttpNetworkConfig.decode(configExceptAccounts);
344
444
  if (netConfigResult.isLeft()) {
345
445
  errors.push(
346
446
  getErrorMessage(
@@ -350,6 +450,38 @@ export function getValidationErrors(config: any): string[] {
350
450
  )
351
451
  );
352
452
  }
453
+
454
+ // manual validation of accounts
455
+ if (Array.isArray(accounts)) {
456
+ accounts.forEach((privateKey, index) =>
457
+ validatePrivateKey(privateKey, index, networkName, errors)
458
+ );
459
+ } else if (typeof accounts === "object") {
460
+ const hdConfigResult = HDAccountsConfig.decode(accounts);
461
+ if (hdConfigResult.isLeft()) {
462
+ errors.push(
463
+ getErrorMessage(
464
+ `HardhatConfig.networks.${networkName}`,
465
+ accounts,
466
+ "HttpNetworkHDAccountsConfig"
467
+ )
468
+ );
469
+ }
470
+ } else if (typeof accounts === "string") {
471
+ if (accounts !== "remote") {
472
+ errors.push(
473
+ `Invalid 'accounts' entry for network '${networkName}': expected an array of accounts or the string 'remote', but got the string '${accounts}'`
474
+ );
475
+ }
476
+ } else if (accounts !== undefined) {
477
+ errors.push(
478
+ getErrorMessage(
479
+ `HardhatConfig.networks.${networkName}.accounts`,
480
+ accounts,
481
+ '"remote" | string[] | HttpNetworkHDAccountsConfig | undefined'
482
+ )
483
+ );
484
+ }
353
485
  }
354
486
  }
355
487
 
@@ -42,7 +42,13 @@ export const defaultHardhatNetworkParams: Omit<
42
42
  throwOnTransactionFailures: true,
43
43
  throwOnCallFailures: true,
44
44
  allowUnlimitedContractSize: false,
45
- mining: { auto: true, interval: 0 },
45
+ mining: {
46
+ auto: true,
47
+ interval: 0,
48
+ mempool: {
49
+ order: "priority",
50
+ },
51
+ },
46
52
  accounts: defaultHardhatNetworkHdAccountsConfigParams,
47
53
  loggingEnabled: false,
48
54
  gasMultiplier: DEFAULT_GAS_MULTIPLIER,
@@ -571,7 +571,7 @@ Please double check how you invoked Hardhat or ran your task.`,
571
571
  },
572
572
  MISSING_TASK_ARGUMENT: {
573
573
  number: 306,
574
- message: "Missing task argument %param%",
574
+ message: "The '%param%' parameter expects a value, but none was passed.",
575
575
  title: "Missing task argument",
576
576
  description: `You tried to run a task, but one of its required arguments was missing.
577
577
 
@@ -884,7 +884,7 @@ Please use a newer, supported version.`,
884
884
  ARTIFACTS: {
885
885
  NOT_FOUND: {
886
886
  number: 700,
887
- message: 'Artifact for contract "%contractName%" not found.',
887
+ message: 'Artifact for contract "%contractName%" not found. %suggestion%',
888
888
  title: "Artifact not found",
889
889
  description: `Tried to import a nonexistent artifact.
890
890
 
@@ -6,6 +6,7 @@ import { rpcAddress, rpcData, rpcHash, rpcQuantity } from "../base-types";
6
6
  export type RpcLog = t.TypeOf<typeof rpcLog>;
7
7
  export const rpcLog = t.type(
8
8
  {
9
+ logIndex: nullable(rpcQuantity),
9
10
  transactionIndex: nullable(rpcQuantity),
10
11
  transactionHash: nullable(rpcHash),
11
12
  blockHash: nullable(rpcHash),
@@ -78,8 +78,8 @@ export const HARDHAT_PARAM_DEFINITIONS: HardhatParamDefinitions = {
78
78
  tsconfig: {
79
79
  name: "tsconfig",
80
80
  defaultValue: undefined,
81
- description: "Reserved hardhat argument -- Has no effect.",
82
- type: types.string,
81
+ description: "A TypeScript config file.",
82
+ type: types.inputFile,
83
83
  isOptional: true,
84
84
  isFlag: false,
85
85
  isVariadic: false,
@@ -13,7 +13,10 @@ import type {
13
13
  } from "../../../types";
14
14
  import { HARDHAT_NETWORK_NAME } from "../../constants";
15
15
  import { ModulesLogger } from "../../hardhat-network/provider/modules/logger";
16
- import { ForkConfig } from "../../hardhat-network/provider/node-types";
16
+ import {
17
+ ForkConfig,
18
+ MempoolOrder,
19
+ } from "../../hardhat-network/provider/node-types";
17
20
  import { getForkCacheDirPath } from "../../hardhat-network/provider/utils/disk-cache";
18
21
  import { parseDateString } from "../../util/date";
19
22
 
@@ -88,6 +91,8 @@ export function createProvider(
88
91
  hardhatNetConfig.throwOnCallFailures,
89
92
  hardhatNetConfig.mining.auto,
90
93
  hardhatNetConfig.mining.interval,
94
+ // This cast is valid because of the config validation and resolution
95
+ hardhatNetConfig.mining.mempool.order as MempoolOrder,
91
96
  new ModulesLogger(hardhatNetConfig.loggingEnabled),
92
97
  accounts,
93
98
  artifacts,
@@ -97,7 +102,8 @@ export function createProvider(
97
102
  : undefined,
98
103
  experimentalHardhatNetworkMessageTraceHooks,
99
104
  forkConfig,
100
- paths !== undefined ? getForkCacheDirPath(paths) : undefined
105
+ paths !== undefined ? getForkCacheDirPath(paths) : undefined,
106
+ hardhatNetConfig.coinbase
101
107
  );
102
108
  } else {
103
109
  const HttpProvider = importProvider<
@@ -38,7 +38,7 @@ export function isTypescriptSupported() {
38
38
  return cachedIsTypescriptSupported;
39
39
  }
40
40
 
41
- export function loadTsNode() {
41
+ export function loadTsNode(tsConfigPath?: string) {
42
42
  try {
43
43
  require.resolve("typescript");
44
44
  } catch (error) {
@@ -58,6 +58,10 @@ export function loadTsNode() {
58
58
  return;
59
59
  }
60
60
 
61
+ if (tsConfigPath !== undefined) {
62
+ process.env.TS_NODE_PROJECT = tsConfigPath;
63
+ }
64
+
61
65
  // See: https://github.com/nomiclabs/hardhat/issues/265
62
66
  if (process.env.TS_NODE_FILES === undefined) {
63
67
  process.env.TS_NODE_FILES = "true";
@@ -2,7 +2,8 @@ import { TypedTransaction } from "@ethereumjs/tx";
2
2
  import { BN } from "ethereumjs-util";
3
3
  import Heap from "mnemonist/heap";
4
4
 
5
- import { InternalError } from "../../core/providers/errors";
5
+ import { InternalError, InvalidInputError } from "../../core/providers/errors";
6
+ import { MempoolOrder } from "./node-types";
6
7
  import { OrderedTransaction } from "./PoolState";
7
8
 
8
9
  function getEffectiveMinerFee(tx: OrderedTransaction, baseFee?: BN): BN {
@@ -38,6 +39,33 @@ function decreasingOrderEffectiveMinerFeeComparator(
38
39
  // in increasing order by orderId.
39
40
  return left.orderId - right.orderId;
40
41
  }
42
+
43
+ function decreasingOrderComparator(
44
+ left: OrderedTransaction,
45
+ right: OrderedTransaction
46
+ ) {
47
+ return left.orderId - right.orderId;
48
+ }
49
+
50
+ function getOrderedTransactionHeap(
51
+ mempoolOrder: MempoolOrder,
52
+ baseFee?: BN
53
+ ): Heap<OrderedTransaction> {
54
+ switch (mempoolOrder) {
55
+ case "priority":
56
+ return new Heap<OrderedTransaction>((a, b) =>
57
+ decreasingOrderEffectiveMinerFeeComparator(a, b, baseFee)
58
+ );
59
+ case "fifo":
60
+ return new Heap<OrderedTransaction>((a, b) =>
61
+ decreasingOrderComparator(a, b)
62
+ );
63
+ default:
64
+ // eslint-disable-next-line @nomiclabs/hardhat-internal-rules/only-hardhat-error
65
+ throw new InvalidInputError(`Invalid mempool order: ${mempoolOrder}`);
66
+ }
67
+ }
68
+
41
69
  /**
42
70
  * A queue of transactions in the order that they could be mined in the next
43
71
  * block.
@@ -67,11 +95,10 @@ export class TransactionQueue {
67
95
  */
68
96
  constructor(
69
97
  pendingTransactions: Map<string, OrderedTransaction[]>,
98
+ mempoolOrder: MempoolOrder,
70
99
  baseFee?: BN
71
100
  ) {
72
- this._heap = new Heap<OrderedTransaction>((a, b) =>
73
- decreasingOrderEffectiveMinerFeeComparator(a, b, baseFee)
74
- );
101
+ this._heap = getOrderedTransactionHeap(mempoolOrder, baseFee);
75
102
 
76
103
  for (const [address, txList] of pendingTransactions) {
77
104
  if (baseFee === undefined && txList.some((tx) => tx.data.type === 2)) {
@@ -215,9 +215,7 @@ export class ForkBlockchain implements HardhatBlockchainInterface {
215
215
  : filterParams.addresses,
216
216
  topics: filterParams.normalizedTopics,
217
217
  });
218
- return remoteLogs
219
- .map((log, index) => toRpcLogOutput(log, index))
220
- .concat(localLogs);
218
+ return remoteLogs.map(toRpcLogOutput).concat(localLogs);
221
219
  }
222
220
  return this._data.getLogs(filterParams);
223
221
  }
@@ -108,6 +108,9 @@ export class HardhatModule {
108
108
  return this._setNextBlockBaseFeePerGasAction(
109
109
  ...this._setNextBlockBaseFeePerGasParams(params)
110
110
  );
111
+
112
+ case "hardhat_setCoinbase":
113
+ return this._setCoinbaseAction(...this._setCoinbaseParams(params));
111
114
  }
112
115
 
113
116
  throw new MethodNotFoundError(`Method ${method} not found`);
@@ -346,6 +349,17 @@ export class HardhatModule {
346
349
  return true;
347
350
  }
348
351
 
352
+ // hardhat_setCoinbase
353
+
354
+ private _setCoinbaseParams(params: any[]): [Buffer] {
355
+ return validateParams(params, rpcAddress);
356
+ }
357
+
358
+ private async _setCoinbaseAction(address: Buffer) {
359
+ await this._node.setCoinbase(new Address(address));
360
+ return true;
361
+ }
362
+
349
363
  private async _logBlock(result: MineBlockResult) {
350
364
  const { block, traces } = result;
351
365
 
@@ -3,6 +3,7 @@ import { RunBlockResult } from "@ethereumjs/vm/dist/runBlock";
3
3
  import { BN } from "ethereumjs-util";
4
4
 
5
5
  import { BuildInfo } from "../../../types";
6
+ import { HARDHAT_MEMPOOL_SUPPORTED_ORDERS } from "../../constants";
6
7
  import { MessageTrace } from "../stack-traces/message-trace";
7
8
 
8
9
  import type { ReturnData } from "./return-data";
@@ -28,6 +29,8 @@ interface CommonConfig {
28
29
  initialDate?: Date;
29
30
  tracingConfig?: TracingConfig;
30
31
  initialBaseFeePerGas?: number;
32
+ mempoolOrder: MempoolOrder;
33
+ coinbase: string;
31
34
  }
32
35
 
33
36
  export type LocalNodeConfig = CommonConfig;
@@ -48,6 +51,8 @@ export interface TracingConfig {
48
51
 
49
52
  export type IntervalMiningConfig = number | [number, number];
50
53
 
54
+ export type MempoolOrder = typeof HARDHAT_MEMPOOL_SUPPORTED_ORDERS[number];
55
+
51
56
  export interface GenesisAccount {
52
57
  privateKey: string;
53
58
  balance: string | number | BN;
@@ -121,6 +126,7 @@ export interface Snapshot {
121
126
  nextBlockTimestamp: BN;
122
127
  irregularStatesByBlockNumber: Map<string, Buffer>;
123
128
  userProvidedNextBlockBaseFeePerGas: BN | undefined;
129
+ coinbase: string;
124
130
  }
125
131
 
126
132
  export type SendTransactionResult =
@@ -82,6 +82,7 @@ import {
82
82
  GatherTracesResult,
83
83
  GenesisAccount,
84
84
  isForkedNodeConfig,
85
+ MempoolOrder,
85
86
  MineBlockResult,
86
87
  NodeConfig,
87
88
  RunCallResult,
@@ -115,10 +116,6 @@ const log = debug("hardhat:core:hardhat-network:node");
115
116
 
116
117
  const ethSigUtil = require("eth-sig-util");
117
118
 
118
- export const COINBASE_ADDRESS = Address.fromString(
119
- "0xc014ba5ec014ba5ec014ba5ec014ba5ec014ba5e"
120
- );
121
-
122
119
  /* eslint-disable @nomiclabs/hardhat-internal-rules/only-hardhat-error */
123
120
 
124
121
  export class HardhatNode extends EventEmitter {
@@ -132,6 +129,7 @@ export class HardhatNode extends EventEmitter {
132
129
  allowUnlimitedContractSize,
133
130
  tracingConfig,
134
131
  minGasPrice,
132
+ mempoolOrder,
135
133
  } = config;
136
134
 
137
135
  let common: Common;
@@ -242,6 +240,8 @@ export class HardhatNode extends EventEmitter {
242
240
  automine,
243
241
  minGasPrice,
244
242
  initialBlockTimeOffset,
243
+ mempoolOrder,
244
+ config.coinbase,
245
245
  genesisAccounts,
246
246
  tracingConfig,
247
247
  forkNetworkId,
@@ -315,6 +315,8 @@ Hardhat Network's forking functionality only works with blocks from at least spu
315
315
  private _automine: boolean,
316
316
  private _minGasPrice: BN,
317
317
  private _blockTimeOffsetSeconds: BN = new BN(0),
318
+ private _mempoolOrder: MempoolOrder,
319
+ private _coinbase: string,
318
320
  genesisAccounts: GenesisAccount[],
319
321
  tracingConfig?: TracingConfig,
320
322
  private _forkNetworkId?: number,
@@ -697,7 +699,7 @@ Hardhat Network's forking functionality only works with blocks from at least spu
697
699
  }
698
700
 
699
701
  public getCoinbaseAddress(): Address {
700
- return COINBASE_ADDRESS;
702
+ return Address.fromString(this._coinbase);
701
703
  }
702
704
 
703
705
  public async getStorageAt(
@@ -870,6 +872,7 @@ Hardhat Network's forking functionality only works with blocks from at least spu
870
872
  irregularStatesByBlockNumber: this._irregularStatesByBlockNumber,
871
873
  userProvidedNextBlockBaseFeePerGas:
872
874
  this.getUserProvidedNextBlockBaseFeePerGas(),
875
+ coinbase: this.getCoinbaseAddress().toString(),
873
876
  };
874
877
 
875
878
  this._irregularStatesByBlockNumber = new Map(
@@ -924,6 +927,8 @@ Hardhat Network's forking functionality only works with blocks from at least spu
924
927
  this._resetUserProvidedNextBlockBaseFeePerGas();
925
928
  }
926
929
 
930
+ this._coinbase = snapshot.coinbase;
931
+
927
932
  // We delete this and the following snapshots, as they can only be used
928
933
  // once in Ganache
929
934
  this._snapshots.splice(snapshotIndex);
@@ -1349,6 +1354,10 @@ Hardhat Network's forking functionality only works with blocks from at least spu
1349
1354
  };
1350
1355
  }
1351
1356
 
1357
+ public async setCoinbase(coinbase: Address) {
1358
+ this._coinbase = coinbase.toString();
1359
+ }
1360
+
1352
1361
  private _getGasUsedRatio(block: Block): number {
1353
1362
  const FLOATS_PRECISION = 100_000;
1354
1363
 
@@ -1579,6 +1588,7 @@ Hardhat Network's forking functionality only works with blocks from at least spu
1579
1588
  const pendingTxs = this._txPool.getPendingTransactions();
1580
1589
  const transactionQueue = new TransactionQueue(
1581
1590
  pendingTxs,
1591
+ this._mempoolOrder,
1582
1592
  headerData.baseFeePerGas
1583
1593
  );
1584
1594
 
@@ -292,18 +292,18 @@ export function getRpcReceiptOutputsFromLocalBlockExecution(
292
292
  ): RpcReceiptOutput[] {
293
293
  const receipts: RpcReceiptOutput[] = [];
294
294
 
295
- let cumulativeGasUsed = new BN(0);
295
+ let blockLogIndex = 0;
296
296
 
297
297
  for (let i = 0; i < runBlockResult.results.length; i += 1) {
298
298
  const tx = block.transactions[i];
299
299
  const { createdAddress, gasUsed } = runBlockResult.results[i];
300
300
  const receipt = runBlockResult.receipts[i];
301
301
 
302
- cumulativeGasUsed = cumulativeGasUsed.add(new BN(receipt.gasUsed));
303
-
304
- const logs = receipt.logs.map((log, logIndex) =>
305
- getRpcLogOutput(log, tx, block, i, logIndex)
306
- );
302
+ const logs = receipt.logs.map((log) => {
303
+ const result = getRpcLogOutput(log, tx, block, i, blockLogIndex);
304
+ blockLogIndex += 1;
305
+ return result;
306
+ });
307
307
 
308
308
  const rpcReceipt: RpcReceiptOutput = {
309
309
  transactionHash: bufferToRpcData(tx.hash()),
@@ -312,7 +312,7 @@ export function getRpcReceiptOutputsFromLocalBlockExecution(
312
312
  blockNumber: numberToRpcQuantity(new BN(block.header.number)),
313
313
  from: bufferToRpcData(tx.getSenderAddress().toBuffer()),
314
314
  to: tx.to === undefined ? null : bufferToRpcData(tx.to.toBuffer()),
315
- cumulativeGasUsed: numberToRpcQuantity(cumulativeGasUsed),
315
+ cumulativeGasUsed: numberToRpcQuantity(new BN(receipt.gasUsed)),
316
316
  gasUsed: numberToRpcQuantity(gasUsed),
317
317
  contractAddress:
318
318
  createdAddress !== undefined
@@ -395,7 +395,7 @@ export function remoteReceiptToRpcReceiptOutput(
395
395
  };
396
396
  }
397
397
 
398
- export function toRpcLogOutput(log: RpcLog, index?: number): RpcLogOutput {
398
+ export function toRpcLogOutput(log: RpcLog): RpcLogOutput {
399
399
  return {
400
400
  removed: false,
401
401
  address: bufferToRpcData(log.address),
@@ -403,7 +403,7 @@ export function toRpcLogOutput(log: RpcLog, index?: number): RpcLogOutput {
403
403
  blockNumber:
404
404
  log.blockNumber !== null ? numberToRpcQuantity(log.blockNumber) : null,
405
405
  data: bufferToRpcData(log.data),
406
- logIndex: index !== undefined ? numberToRpcQuantity(index) : null,
406
+ logIndex: log.logIndex !== null ? numberToRpcQuantity(log.logIndex) : null,
407
407
  transactionIndex:
408
408
  log.transactionIndex !== null
409
409
  ? numberToRpcQuantity(log.transactionIndex)
@@ -40,6 +40,7 @@ import {
40
40
  ForkConfig,
41
41
  GenesisAccount,
42
42
  IntervalMiningConfig,
43
+ MempoolOrder,
43
44
  NodeConfig,
44
45
  TracingConfig,
45
46
  } from "./node-types";
@@ -54,6 +55,8 @@ const PRIVATE_RPC_METHODS = new Set([
54
55
 
55
56
  /* eslint-disable @nomiclabs/hardhat-internal-rules/only-hardhat-error */
56
57
 
58
+ export const DEFAULT_COINBASE = "0xc014ba5ec014ba5ec014ba5ec014ba5ec014ba5e";
59
+
57
60
  export class HardhatNetworkProvider
58
61
  extends EventEmitter
59
62
  implements EIP1193Provider
@@ -81,6 +84,7 @@ export class HardhatNetworkProvider
81
84
  private readonly _throwOnCallFailures: boolean,
82
85
  private readonly _automine: boolean,
83
86
  private readonly _intervalMining: IntervalMiningConfig,
87
+ private readonly _mempoolOrder: MempoolOrder,
84
88
  private readonly _logger: ModulesLogger,
85
89
  private readonly _genesisAccounts: GenesisAccount[] = [],
86
90
  private readonly _artifacts?: Artifacts,
@@ -88,7 +92,8 @@ export class HardhatNetworkProvider
88
92
  private readonly _initialDate?: Date,
89
93
  private readonly _experimentalHardhatNetworkMessageTraceHooks: BoundExperimentalHardhatNetworkMessageTraceHook[] = [],
90
94
  private _forkConfig?: ForkConfig,
91
- private readonly _forkCachePath?: string
95
+ private readonly _forkCachePath?: string,
96
+ private readonly _coinbase = DEFAULT_COINBASE
92
97
  ) {
93
98
  super();
94
99
  }
@@ -227,6 +232,7 @@ export class HardhatNetworkProvider
227
232
  allowUnlimitedContractSize: this._allowUnlimitedContractSize,
228
233
  tracingConfig: await this._makeTracingConfig(),
229
234
  initialBaseFeePerGas: this._initialBaseFeePerGas,
235
+ mempoolOrder: this._mempoolOrder,
230
236
  hardfork: this._hardfork,
231
237
  networkName: this._networkName,
232
238
  chainId: this._chainId,
@@ -235,6 +241,7 @@ export class HardhatNetworkProvider
235
241
  forkConfig: this._forkConfig,
236
242
  forkCachePath:
237
243
  this._forkConfig !== undefined ? this._forkCachePath : undefined,
244
+ coinbase: this._coinbase,
238
245
  };
239
246
 
240
247
  const [common, node] = await HardhatNode.create(config);
package/src/register.ts CHANGED
@@ -36,7 +36,7 @@ if (!HardhatContext.isCreated()) {
36
36
  }
37
37
 
38
38
  if (willRunWithTypescript(hardhatArguments.config)) {
39
- loadTsNode();
39
+ loadTsNode(hardhatArguments.tsconfig);
40
40
  }
41
41
 
42
42
  const config = loadConfigAndTasks(hardhatArguments);