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.
- package/CHANGELOG.md +17 -0
- package/builtin-tasks/node.js +2 -2
- package/internal/artifacts.d.ts +49 -0
- package/internal/artifacts.d.ts.map +1 -1
- package/internal/artifacts.js +191 -55
- package/internal/artifacts.js.map +1 -1
- package/internal/cli/analytics.js +2 -2
- package/internal/cli/analytics.js.map +1 -1
- package/internal/cli/cli.js +1 -1
- package/internal/cli/cli.js.map +1 -1
- package/internal/constants.d.ts +2 -0
- package/internal/constants.d.ts.map +1 -1
- package/internal/constants.js +3 -1
- package/internal/constants.js.map +1 -1
- package/internal/core/config/config-loading.d.ts.map +1 -1
- package/internal/core/config/config-loading.js +15 -1
- package/internal/core/config/config-loading.js.map +1 -1
- package/internal/core/config/config-resolution.d.ts.map +1 -1
- package/internal/core/config/config-resolution.js +21 -0
- package/internal/core/config/config-resolution.js.map +1 -1
- package/internal/core/config/config-validation.d.ts +1 -0
- package/internal/core/config/config-validation.d.ts.map +1 -1
- package/internal/core/config/config-validation.js +88 -13
- package/internal/core/config/config-validation.js.map +1 -1
- package/internal/core/config/default-config.d.ts.map +1 -1
- package/internal/core/config/default-config.js +7 -1
- package/internal/core/config/default-config.js.map +1 -1
- package/internal/core/errors-list.js +2 -2
- package/internal/core/errors-list.js.map +1 -1
- package/internal/core/jsonrpc/types/output/log.d.ts +1 -0
- package/internal/core/jsonrpc/types/output/log.d.ts.map +1 -1
- package/internal/core/jsonrpc/types/output/log.js +1 -0
- package/internal/core/jsonrpc/types/output/log.js.map +1 -1
- package/internal/core/jsonrpc/types/output/receipt.d.ts +1 -0
- package/internal/core/jsonrpc/types/output/receipt.d.ts.map +1 -1
- package/internal/core/params/hardhat-params.js +2 -2
- package/internal/core/params/hardhat-params.js.map +1 -1
- package/internal/core/providers/construction.d.ts.map +1 -1
- package/internal/core/providers/construction.js +4 -2
- package/internal/core/providers/construction.js.map +1 -1
- package/internal/core/typescript-support.d.ts +1 -1
- package/internal/core/typescript-support.d.ts.map +1 -1
- package/internal/core/typescript-support.js +4 -1
- package/internal/core/typescript-support.js.map +1 -1
- package/internal/hardhat-network/jsonrpc/client.d.ts +2 -0
- package/internal/hardhat-network/jsonrpc/client.d.ts.map +1 -1
- package/internal/hardhat-network/provider/TransactionQueue.d.ts +2 -1
- package/internal/hardhat-network/provider/TransactionQueue.d.ts.map +1 -1
- package/internal/hardhat-network/provider/TransactionQueue.js +16 -2
- package/internal/hardhat-network/provider/TransactionQueue.js.map +1 -1
- package/internal/hardhat-network/provider/fork/ForkBlockchain.d.ts.map +1 -1
- package/internal/hardhat-network/provider/fork/ForkBlockchain.js +1 -3
- package/internal/hardhat-network/provider/fork/ForkBlockchain.js.map +1 -1
- package/internal/hardhat-network/provider/modules/hardhat.d.ts +2 -0
- package/internal/hardhat-network/provider/modules/hardhat.d.ts.map +1 -1
- package/internal/hardhat-network/provider/modules/hardhat.js +10 -0
- package/internal/hardhat-network/provider/modules/hardhat.js.map +1 -1
- package/internal/hardhat-network/provider/node-types.d.ts +5 -0
- package/internal/hardhat-network/provider/node-types.d.ts.map +1 -1
- package/internal/hardhat-network/provider/node-types.js.map +1 -1
- package/internal/hardhat-network/provider/node.d.ts +3 -1
- package/internal/hardhat-network/provider/node.d.ts.map +1 -1
- package/internal/hardhat-network/provider/node.js +13 -7
- package/internal/hardhat-network/provider/node.js.map +1 -1
- package/internal/hardhat-network/provider/output.d.ts +1 -1
- package/internal/hardhat-network/provider/output.d.ts.map +1 -1
- package/internal/hardhat-network/provider/output.js +9 -6
- package/internal/hardhat-network/provider/output.js.map +1 -1
- package/internal/hardhat-network/provider/provider.d.ts +5 -2
- package/internal/hardhat-network/provider/provider.d.ts.map +1 -1
- package/internal/hardhat-network/provider/provider.js +7 -2
- package/internal/hardhat-network/provider/provider.js.map +1 -1
- package/package.json +4 -4
- package/register.js +1 -1
- package/register.js.map +1 -1
- package/src/builtin-tasks/node.ts +2 -2
- package/src/internal/artifacts.ts +268 -71
- package/src/internal/cli/analytics.ts +1 -1
- package/src/internal/cli/cli.ts +1 -1
- package/src/internal/constants.ts +3 -0
- package/src/internal/core/config/config-loading.ts +23 -1
- package/src/internal/core/config/config-resolution.ts +28 -0
- package/src/internal/core/config/config-validation.ts +147 -15
- package/src/internal/core/config/default-config.ts +7 -1
- package/src/internal/core/errors-list.ts +2 -2
- package/src/internal/core/jsonrpc/types/output/log.ts +1 -0
- package/src/internal/core/params/hardhat-params.ts +2 -2
- package/src/internal/core/providers/construction.ts +8 -2
- package/src/internal/core/typescript-support.ts +5 -1
- package/src/internal/hardhat-network/provider/TransactionQueue.ts +31 -4
- package/src/internal/hardhat-network/provider/fork/ForkBlockchain.ts +1 -3
- package/src/internal/hardhat-network/provider/modules/hardhat.ts +14 -0
- package/src/internal/hardhat-network/provider/node-types.ts +6 -0
- package/src/internal/hardhat-network/provider/node.ts +15 -5
- package/src/internal/hardhat-network/provider/output.ts +9 -9
- package/src/internal/hardhat-network/provider/provider.ts +8 -1
- package/src/register.ts +1 -1
- package/src/types/config.ts +14 -0
- package/src/utils/contract-names.ts +112 -0
- package/src/utils/source-names.ts +1 -1
- package/types/config.d.ts +10 -0
- package/types/config.d.ts.map +1 -1
- package/utils/contract-names.d.ts +10 -0
- package/utils/contract-names.d.ts.map +1 -1
- package/utils/contract-names.js +92 -1
- package/utils/contract-names.js.map +1 -1
- package/utils/source-names.d.ts +1 -1
- 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 =
|
|
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
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
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
|
-
|
|
368
|
+
balance,
|
|
271
369
|
"string"
|
|
272
370
|
)
|
|
273
371
|
);
|
|
274
|
-
} else if (decimalString.decode(
|
|
372
|
+
} else if (decimalString.decode(balance).isLeft()) {
|
|
275
373
|
errors.push(
|
|
276
374
|
getErrorMessage(
|
|
277
375
|
`HardhatConfig.networks.${HARDHAT_NETWORK_NAME}.accounts[].balance`,
|
|
278
|
-
|
|
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
|
|
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: {
|
|
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: "
|
|
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: "
|
|
82
|
-
type: types.
|
|
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 {
|
|
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 =
|
|
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
|
|
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
|
|
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
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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(
|
|
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
|
|
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:
|
|
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);
|