hardhat 2.17.3 → 2.17.4
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/internal/cli/cli.js +42 -14
- package/internal/cli/cli.js.map +1 -1
- package/internal/core/errors-list.d.ts +14 -0
- package/internal/core/errors-list.d.ts.map +1 -1
- package/internal/core/errors-list.js +16 -0
- package/internal/core/errors-list.js.map +1 -1
- package/internal/core/jsonrpc/types/input/blockTag.d.ts +3 -3
- package/internal/core/jsonrpc/types/input/filterRequest.d.ts +6 -6
- package/internal/hardhat-network/provider/modules/base.d.ts +17 -0
- package/internal/hardhat-network/provider/modules/base.d.ts.map +1 -0
- package/internal/hardhat-network/provider/modules/base.js +127 -0
- package/internal/hardhat-network/provider/modules/base.js.map +1 -0
- package/internal/hardhat-network/provider/modules/debug.d.ts +5 -3
- package/internal/hardhat-network/provider/modules/debug.d.ts.map +1 -1
- package/internal/hardhat-network/provider/modules/debug.js +21 -5
- package/internal/hardhat-network/provider/modules/debug.js.map +1 -1
- package/internal/hardhat-network/provider/modules/eth.d.ts +2 -7
- package/internal/hardhat-network/provider/modules/eth.d.ts.map +1 -1
- package/internal/hardhat-network/provider/modules/eth.js +12 -60
- package/internal/hardhat-network/provider/modules/eth.js.map +1 -1
- package/internal/hardhat-network/provider/node.d.ts +1 -0
- package/internal/hardhat-network/provider/node.d.ts.map +1 -1
- package/internal/hardhat-network/provider/node.js +6 -0
- package/internal/hardhat-network/provider/node.js.map +1 -1
- package/package.json +1 -1
- package/src/internal/cli/cli.ts +65 -15
- package/src/internal/core/errors-list.ts +18 -0
- package/src/internal/hardhat-network/provider/modules/base.ts +156 -0
- package/src/internal/hardhat-network/provider/modules/debug.ts +50 -9
- package/src/internal/hardhat-network/provider/modules/eth.ts +16 -91
- package/src/internal/hardhat-network/provider/node.ts +12 -0
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { rpcHash } from "../../../core/jsonrpc/types/base-types";
|
|
2
|
+
import {
|
|
3
|
+
OptionalRpcNewBlockTag,
|
|
4
|
+
optionalRpcNewBlockTag,
|
|
5
|
+
} from "../../../core/jsonrpc/types/input/blockTag";
|
|
6
|
+
import {
|
|
7
|
+
RpcCallRequest,
|
|
8
|
+
rpcCallRequest,
|
|
9
|
+
} from "../../../core/jsonrpc/types/input/callRequest";
|
|
2
10
|
import {
|
|
3
11
|
rpcDebugTracingConfig,
|
|
4
12
|
RpcDebugTracingConfig,
|
|
@@ -10,17 +18,22 @@ import {
|
|
|
10
18
|
} from "../../../core/providers/errors";
|
|
11
19
|
import { HardhatNode } from "../node";
|
|
12
20
|
import { RpcDebugTraceOutput } from "../output";
|
|
21
|
+
import { Base } from "./base";
|
|
13
22
|
|
|
14
23
|
/* eslint-disable @nomicfoundation/hardhat-internal-rules/only-hardhat-error */
|
|
15
24
|
|
|
16
|
-
export class DebugModule {
|
|
17
|
-
constructor(
|
|
25
|
+
export class DebugModule extends Base {
|
|
26
|
+
constructor(_node: HardhatNode) {
|
|
27
|
+
super(_node);
|
|
28
|
+
}
|
|
18
29
|
|
|
19
30
|
public async processRequest(
|
|
20
31
|
method: string,
|
|
21
32
|
params: any[] = []
|
|
22
33
|
): Promise<any> {
|
|
23
34
|
switch (method) {
|
|
35
|
+
case "debug_traceCall":
|
|
36
|
+
return this._traceCallAction(...this._traceCallParams(params));
|
|
24
37
|
case "debug_traceTransaction":
|
|
25
38
|
return this._traceTransactionAction(
|
|
26
39
|
...this._traceTransactionParams(params)
|
|
@@ -30,6 +43,34 @@ export class DebugModule {
|
|
|
30
43
|
throw new MethodNotFoundError(`Method ${method} not found`);
|
|
31
44
|
}
|
|
32
45
|
|
|
46
|
+
// debug_traceCall
|
|
47
|
+
|
|
48
|
+
private _traceCallParams(
|
|
49
|
+
params: any[]
|
|
50
|
+
): [RpcCallRequest, OptionalRpcNewBlockTag, RpcDebugTracingConfig] {
|
|
51
|
+
const validatedParams = validateParams(
|
|
52
|
+
params,
|
|
53
|
+
rpcCallRequest,
|
|
54
|
+
optionalRpcNewBlockTag,
|
|
55
|
+
rpcDebugTracingConfig
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
this._validateTracerParam(validatedParams[2]);
|
|
59
|
+
|
|
60
|
+
return validatedParams;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private async _traceCallAction(
|
|
64
|
+
callConfig: RpcCallRequest,
|
|
65
|
+
block: OptionalRpcNewBlockTag,
|
|
66
|
+
traceConfig: RpcDebugTracingConfig
|
|
67
|
+
): Promise<RpcDebugTraceOutput> {
|
|
68
|
+
const callParams = await this.rpcCallRequestToNodeCallParams(callConfig);
|
|
69
|
+
const blockNumber = await this.resolveNewBlockTag(block);
|
|
70
|
+
|
|
71
|
+
return this._node.traceCall(callParams, blockNumber, traceConfig);
|
|
72
|
+
}
|
|
73
|
+
|
|
33
74
|
// debug_traceTransaction
|
|
34
75
|
|
|
35
76
|
private _traceTransactionParams(
|
|
@@ -46,6 +87,13 @@ export class DebugModule {
|
|
|
46
87
|
return validatedParams;
|
|
47
88
|
}
|
|
48
89
|
|
|
90
|
+
private async _traceTransactionAction(
|
|
91
|
+
hash: Buffer,
|
|
92
|
+
config: RpcDebugTracingConfig
|
|
93
|
+
): Promise<RpcDebugTraceOutput> {
|
|
94
|
+
return this._node.traceTransaction(hash, config);
|
|
95
|
+
}
|
|
96
|
+
|
|
49
97
|
private _validateTracerParam(config: RpcDebugTracingConfig) {
|
|
50
98
|
if (config?.tracer !== undefined) {
|
|
51
99
|
throw new InvalidArgumentsError(
|
|
@@ -53,11 +101,4 @@ export class DebugModule {
|
|
|
53
101
|
);
|
|
54
102
|
}
|
|
55
103
|
}
|
|
56
|
-
|
|
57
|
-
private async _traceTransactionAction(
|
|
58
|
-
hash: Buffer,
|
|
59
|
-
config: RpcDebugTracingConfig
|
|
60
|
-
): Promise<RpcDebugTraceOutput> {
|
|
61
|
-
return this._node.traceTransaction(hash, config);
|
|
62
|
-
}
|
|
63
104
|
}
|
|
@@ -5,18 +5,10 @@ import {
|
|
|
5
5
|
TransactionFactory,
|
|
6
6
|
TypedTransaction,
|
|
7
7
|
} from "@nomicfoundation/ethereumjs-tx";
|
|
8
|
-
import {
|
|
9
|
-
Address,
|
|
10
|
-
bufferToHex,
|
|
11
|
-
toBuffer,
|
|
12
|
-
toRpcSig,
|
|
13
|
-
zeroAddress,
|
|
14
|
-
} from "@nomicfoundation/ethereumjs-util";
|
|
8
|
+
import { Address, toBuffer, toRpcSig } from "@nomicfoundation/ethereumjs-util";
|
|
15
9
|
import * as t from "io-ts";
|
|
16
10
|
import cloneDeep from "lodash/cloneDeep";
|
|
17
|
-
|
|
18
11
|
import { BoundExperimentalHardhatNetworkMessageTraceHook } from "../../../../types";
|
|
19
|
-
import { RpcAccessList } from "../../../core/jsonrpc/types/access-list";
|
|
20
12
|
import {
|
|
21
13
|
bufferToRpcData,
|
|
22
14
|
numberToRpcQuantity,
|
|
@@ -69,7 +61,6 @@ import { MessageTrace } from "../../stack-traces/message-trace";
|
|
|
69
61
|
import { LATEST_BLOCK } from "../filter";
|
|
70
62
|
import { HardhatNode } from "../node";
|
|
71
63
|
import {
|
|
72
|
-
CallParams,
|
|
73
64
|
FilterParams,
|
|
74
65
|
GatherTracesResult,
|
|
75
66
|
MineBlockResult,
|
|
@@ -90,6 +81,7 @@ import { optional } from "../../../util/io-ts";
|
|
|
90
81
|
import * as BigIntUtils from "../../../util/bigint";
|
|
91
82
|
import { HardforkName } from "../../../util/hardforks";
|
|
92
83
|
import { ModulesLogger } from "./logger";
|
|
84
|
+
import { Base } from "./base";
|
|
93
85
|
|
|
94
86
|
const EIP1559_MIN_HARDFORK = HardforkName.LONDON;
|
|
95
87
|
const ACCESS_LIST_MIN_HARDFORK = HardforkName.BERLIN;
|
|
@@ -97,15 +89,17 @@ const EIP155_MIN_HARDFORK = HardforkName.SPURIOUS_DRAGON;
|
|
|
97
89
|
const EIP3860_MIN_HARDFORK = HardforkName.SHANGHAI;
|
|
98
90
|
|
|
99
91
|
/* eslint-disable @nomicfoundation/hardhat-internal-rules/only-hardhat-error */
|
|
100
|
-
export class EthModule {
|
|
92
|
+
export class EthModule extends Base {
|
|
101
93
|
constructor(
|
|
102
94
|
private readonly _common: Common,
|
|
103
|
-
|
|
95
|
+
_node: HardhatNode,
|
|
104
96
|
private readonly _throwOnTransactionFailures: boolean,
|
|
105
97
|
private readonly _throwOnCallFailures: boolean,
|
|
106
98
|
private readonly _logger: ModulesLogger,
|
|
107
99
|
private readonly _experimentalHardhatNetworkMessageTraceHooks: BoundExperimentalHardhatNetworkMessageTraceHook[] = []
|
|
108
|
-
) {
|
|
100
|
+
) {
|
|
101
|
+
super(_node);
|
|
102
|
+
}
|
|
109
103
|
|
|
110
104
|
public async processRequest(
|
|
111
105
|
method: string,
|
|
@@ -354,9 +348,9 @@ export class EthModule {
|
|
|
354
348
|
): Promise<string> {
|
|
355
349
|
this._validateTransactionAndCallRequest(rpcCall);
|
|
356
350
|
|
|
357
|
-
const blockNumberOrPending = await this.
|
|
351
|
+
const blockNumberOrPending = await this.resolveNewBlockTag(blockTag);
|
|
358
352
|
|
|
359
|
-
const callParams = await this.
|
|
353
|
+
const callParams = await this.rpcCallRequestToNodeCallParams(rpcCall);
|
|
360
354
|
|
|
361
355
|
const {
|
|
362
356
|
result: returnData,
|
|
@@ -434,12 +428,12 @@ export class EthModule {
|
|
|
434
428
|
|
|
435
429
|
// estimateGas behaves differently when there's no blockTag
|
|
436
430
|
// it uses "pending" as default instead of "latest"
|
|
437
|
-
const blockNumberOrPending = await this.
|
|
431
|
+
const blockNumberOrPending = await this.resolveNewBlockTag(
|
|
438
432
|
blockTag,
|
|
439
433
|
"pending"
|
|
440
434
|
);
|
|
441
435
|
|
|
442
|
-
const callParams = await this.
|
|
436
|
+
const callParams = await this.rpcCallRequestToNodeCallParams(callRequest);
|
|
443
437
|
|
|
444
438
|
const { estimation, error, trace, consoleLogMessages } =
|
|
445
439
|
await this._node.estimateGas(callParams, blockNumberOrPending);
|
|
@@ -487,7 +481,7 @@ export class EthModule {
|
|
|
487
481
|
address: Buffer,
|
|
488
482
|
blockTag: OptionalRpcNewBlockTag
|
|
489
483
|
): Promise<string> {
|
|
490
|
-
const blockNumberOrPending = await this.
|
|
484
|
+
const blockNumberOrPending = await this.resolveNewBlockTag(blockTag);
|
|
491
485
|
|
|
492
486
|
return numberToRpcQuantity(
|
|
493
487
|
await this._node.getAccountBalance(
|
|
@@ -612,7 +606,7 @@ export class EthModule {
|
|
|
612
606
|
address: Buffer,
|
|
613
607
|
blockTag: OptionalRpcNewBlockTag
|
|
614
608
|
): Promise<string> {
|
|
615
|
-
const blockNumberOrPending = await this.
|
|
609
|
+
const blockNumberOrPending = await this.resolveNewBlockTag(blockTag);
|
|
616
610
|
|
|
617
611
|
return bufferToRpcData(
|
|
618
612
|
await this._node.getCode(new Address(address), blockNumberOrPending)
|
|
@@ -721,7 +715,7 @@ export class EthModule {
|
|
|
721
715
|
slot: bigint,
|
|
722
716
|
blockTag: OptionalRpcNewBlockTag
|
|
723
717
|
): Promise<string> {
|
|
724
|
-
const blockNumberOrPending = await this.
|
|
718
|
+
const blockNumberOrPending = await this.resolveNewBlockTag(blockTag);
|
|
725
719
|
|
|
726
720
|
const data = await this._node.getStorageAt(
|
|
727
721
|
new Address(address),
|
|
@@ -854,7 +848,7 @@ export class EthModule {
|
|
|
854
848
|
address: Buffer,
|
|
855
849
|
blockTag: OptionalRpcNewBlockTag
|
|
856
850
|
): Promise<string> {
|
|
857
|
-
const blockNumberOrPending = await this.
|
|
851
|
+
const blockNumberOrPending = await this.resolveNewBlockTag(blockTag);
|
|
858
852
|
|
|
859
853
|
return numberToRpcQuantity(
|
|
860
854
|
await this._node.getNextConfirmedNonce(
|
|
@@ -1240,7 +1234,7 @@ export class EthModule {
|
|
|
1240
1234
|
);
|
|
1241
1235
|
}
|
|
1242
1236
|
|
|
1243
|
-
const resolvedNewestBlock = await this.
|
|
1237
|
+
const resolvedNewestBlock = await this.resolveNewBlockTag(newestBlock);
|
|
1244
1238
|
|
|
1245
1239
|
const feeHistory = await this._node.getFeeHistory(
|
|
1246
1240
|
blockCount,
|
|
@@ -1263,29 +1257,6 @@ export class EthModule {
|
|
|
1263
1257
|
|
|
1264
1258
|
// Utility methods
|
|
1265
1259
|
|
|
1266
|
-
private async _rpcCallRequestToNodeCallParams(
|
|
1267
|
-
rpcCall: RpcCallRequest
|
|
1268
|
-
): Promise<CallParams> {
|
|
1269
|
-
return {
|
|
1270
|
-
to: rpcCall.to,
|
|
1271
|
-
from:
|
|
1272
|
-
rpcCall.from !== undefined
|
|
1273
|
-
? rpcCall.from
|
|
1274
|
-
: await this._getDefaultCallFrom(),
|
|
1275
|
-
data: rpcCall.data !== undefined ? rpcCall.data : toBuffer([]),
|
|
1276
|
-
gasLimit:
|
|
1277
|
-
rpcCall.gas !== undefined ? rpcCall.gas : this._node.getBlockGasLimit(),
|
|
1278
|
-
value: rpcCall.value !== undefined ? rpcCall.value : 0n,
|
|
1279
|
-
accessList:
|
|
1280
|
-
rpcCall.accessList !== undefined
|
|
1281
|
-
? this._rpcAccessListToNodeAccessList(rpcCall.accessList)
|
|
1282
|
-
: undefined,
|
|
1283
|
-
gasPrice: rpcCall.gasPrice,
|
|
1284
|
-
maxFeePerGas: rpcCall.maxFeePerGas,
|
|
1285
|
-
maxPriorityFeePerGas: rpcCall.maxPriorityFeePerGas,
|
|
1286
|
-
};
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
1260
|
private async _rpcTransactionRequestToNodeTransactionParams(
|
|
1290
1261
|
rpcTx: RpcTransactionRequest
|
|
1291
1262
|
): Promise<TransactionParams> {
|
|
@@ -1365,15 +1336,6 @@ export class EthModule {
|
|
|
1365
1336
|
};
|
|
1366
1337
|
}
|
|
1367
1338
|
|
|
1368
|
-
private _rpcAccessListToNodeAccessList(
|
|
1369
|
-
rpcAccessList: RpcAccessList
|
|
1370
|
-
): Array<[Buffer, Buffer[]]> {
|
|
1371
|
-
return rpcAccessList.map((tuple) => [
|
|
1372
|
-
tuple.address,
|
|
1373
|
-
tuple.storageKeys ?? [],
|
|
1374
|
-
]);
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
1339
|
private async _resolveOldBlockTag(
|
|
1378
1340
|
oldBlockTag: RpcOldBlockTag
|
|
1379
1341
|
): Promise<bigint | "pending" | undefined> {
|
|
@@ -1485,22 +1447,6 @@ export class EthModule {
|
|
|
1485
1447
|
return blockTag;
|
|
1486
1448
|
}
|
|
1487
1449
|
|
|
1488
|
-
private _newBlockTagToString(tag: RpcNewBlockTag): string {
|
|
1489
|
-
if (typeof tag === "string") {
|
|
1490
|
-
return tag;
|
|
1491
|
-
}
|
|
1492
|
-
|
|
1493
|
-
if (BigIntUtils.isBigInt(tag)) {
|
|
1494
|
-
return tag.toString();
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
if ("blockNumber" in tag) {
|
|
1498
|
-
return tag.blockNumber.toString();
|
|
1499
|
-
}
|
|
1500
|
-
|
|
1501
|
-
return bufferToHex(tag.blockHash);
|
|
1502
|
-
}
|
|
1503
|
-
|
|
1504
1450
|
private _extractNormalizedLogTopics(
|
|
1505
1451
|
topics: OptionalRpcLogTopics
|
|
1506
1452
|
): Array<Array<Buffer | null> | null> {
|
|
@@ -1532,16 +1478,6 @@ export class EthModule {
|
|
|
1532
1478
|
return address;
|
|
1533
1479
|
}
|
|
1534
1480
|
|
|
1535
|
-
private async _getDefaultCallFrom(): Promise<Buffer> {
|
|
1536
|
-
const localAccounts = await this._node.getLocalAccountAddresses();
|
|
1537
|
-
|
|
1538
|
-
if (localAccounts.length === 0) {
|
|
1539
|
-
return toBuffer(zeroAddress());
|
|
1540
|
-
}
|
|
1541
|
-
|
|
1542
|
-
return toBuffer(localAccounts[0]);
|
|
1543
|
-
}
|
|
1544
|
-
|
|
1545
1481
|
private async _sendTransactionAndReturnHash(tx: TypedTransaction) {
|
|
1546
1482
|
let result = await this._node.sendTransaction(tx);
|
|
1547
1483
|
|
|
@@ -1816,15 +1752,4 @@ You can use them by running Hardhat Network with 'hardfork' ${EIP1559_MIN_HARDFO
|
|
|
1816
1752
|
);
|
|
1817
1753
|
}
|
|
1818
1754
|
}
|
|
1819
|
-
|
|
1820
|
-
private _checkPostMergeBlockTags(blockTag: "safe" | "finalized") {
|
|
1821
|
-
const isPostMerge = this._node.isPostMergeHardfork();
|
|
1822
|
-
const hardfork = this._node.hardfork;
|
|
1823
|
-
|
|
1824
|
-
if (!isPostMerge) {
|
|
1825
|
-
throw new InvalidArgumentsError(
|
|
1826
|
-
`The '${blockTag}' block tag is not allowed in pre-merge hardforks. You are using the '${hardfork}' hardfork.`
|
|
1827
|
-
);
|
|
1828
|
-
}
|
|
1829
|
-
}
|
|
1830
1755
|
}
|
|
@@ -1377,6 +1377,18 @@ Hardhat Network's forking functionality only works with blocks from at least spu
|
|
|
1377
1377
|
await this._persistIrregularWorldState();
|
|
1378
1378
|
}
|
|
1379
1379
|
|
|
1380
|
+
public async traceCall(
|
|
1381
|
+
callParams: CallParams,
|
|
1382
|
+
block: bigint | "pending",
|
|
1383
|
+
traceConfig: RpcDebugTracingConfig
|
|
1384
|
+
) {
|
|
1385
|
+
const vmDebugTracer = new VMDebugTracer(this._vm);
|
|
1386
|
+
|
|
1387
|
+
return vmDebugTracer.trace(async () => {
|
|
1388
|
+
await this.runCall(callParams, block);
|
|
1389
|
+
}, traceConfig);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1380
1392
|
public async traceTransaction(hash: Buffer, config: RpcDebugTracingConfig) {
|
|
1381
1393
|
const block = await this.getBlockByTransactionHash(hash);
|
|
1382
1394
|
if (block === undefined) {
|