hardhat 2.17.1 → 2.17.2
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/builtin-tasks/compile.js +28 -4
- package/builtin-tasks/compile.js.map +1 -1
- package/builtin-tasks/task-names.d.ts +1 -0
- package/builtin-tasks/task-names.d.ts.map +1 -1
- package/builtin-tasks/task-names.js +3 -2
- package/builtin-tasks/task-names.js.map +1 -1
- package/internal/artifacts.d.ts +28 -0
- package/internal/artifacts.d.ts.map +1 -1
- package/internal/artifacts.js +39 -1
- package/internal/artifacts.js.map +1 -1
- package/internal/cli/project-creation.js +1 -1
- package/internal/core/errors-list.d.ts +28 -0
- package/internal/core/errors-list.d.ts.map +1 -1
- package/internal/core/errors-list.js +34 -0
- package/internal/core/errors-list.js.map +1 -1
- package/internal/core/jsonrpc/types/base-types.d.ts +1 -0
- package/internal/core/jsonrpc/types/base-types.d.ts.map +1 -1
- package/internal/core/jsonrpc/types/base-types.js +8 -1
- package/internal/core/jsonrpc/types/base-types.js.map +1 -1
- package/internal/core/jsonrpc/types/input/callRequest.d.ts +60 -0
- package/internal/core/jsonrpc/types/input/callRequest.d.ts.map +1 -1
- package/internal/core/jsonrpc/types/input/callRequest.js +13 -1
- package/internal/core/jsonrpc/types/input/callRequest.js.map +1 -1
- package/internal/core/providers/construction.d.ts.map +1 -1
- package/internal/core/providers/construction.js +1 -0
- package/internal/core/providers/construction.js.map +1 -1
- package/internal/hardhat-network/provider/fork/ForkBlockchain.d.ts.map +1 -1
- package/internal/hardhat-network/provider/fork/ForkBlockchain.js +13 -1
- package/internal/hardhat-network/provider/fork/ForkBlockchain.js.map +1 -1
- package/internal/hardhat-network/provider/modules/eth.d.ts.map +1 -1
- package/internal/hardhat-network/provider/modules/eth.js +3 -3
- package/internal/hardhat-network/provider/modules/eth.js.map +1 -1
- package/internal/hardhat-network/provider/node-types.d.ts +1 -0
- package/internal/hardhat-network/provider/node-types.d.ts.map +1 -1
- package/internal/hardhat-network/provider/node.d.ts +8 -1
- package/internal/hardhat-network/provider/node.d.ts.map +1 -1
- package/internal/hardhat-network/provider/node.js +65 -6
- package/internal/hardhat-network/provider/node.js.map +1 -1
- package/internal/hardhat-network/provider/provider.d.ts +1 -0
- package/internal/hardhat-network/provider/provider.d.ts.map +1 -1
- package/internal/hardhat-network/provider/provider.js +1 -0
- package/internal/hardhat-network/provider/provider.js.map +1 -1
- package/internal/hardhat-network/provider/utils/makeCommon.d.ts +1 -1
- package/internal/hardhat-network/provider/utils/makeCommon.d.ts.map +1 -1
- package/internal/hardhat-network/provider/utils/makeCommon.js +3 -1
- package/internal/hardhat-network/provider/utils/makeCommon.js.map +1 -1
- package/internal/hardhat-network/stack-traces/vm-debug-tracer.d.ts.map +1 -1
- package/internal/hardhat-network/stack-traces/vm-debug-tracer.js +8 -8
- package/internal/hardhat-network/stack-traces/vm-debug-tracer.js.map +1 -1
- package/internal/solidity/dependencyGraph.d.ts.map +1 -1
- package/internal/solidity/dependencyGraph.js +13 -3
- package/internal/solidity/dependencyGraph.js.map +1 -1
- package/internal/solidity/resolver.d.ts +2 -1
- package/internal/solidity/resolver.d.ts.map +1 -1
- package/internal/solidity/resolver.js +31 -17
- package/internal/solidity/resolver.js.map +1 -1
- package/package.json +12 -11
- package/src/builtin-tasks/compile.ts +33 -4
- package/src/builtin-tasks/task-names.ts +1 -0
- package/src/internal/artifacts.ts +40 -1
- package/src/internal/cli/project-creation.ts +1 -1
- package/src/internal/core/errors-list.ts +38 -0
- package/src/internal/core/jsonrpc/types/base-types.ts +15 -0
- package/src/internal/core/jsonrpc/types/input/callRequest.ts +35 -1
- package/src/internal/core/providers/construction.ts +2 -0
- package/src/internal/hardhat-network/provider/fork/ForkBlockchain.ts +24 -4
- package/src/internal/hardhat-network/provider/modules/eth.ts +18 -4
- package/src/internal/hardhat-network/provider/node-types.ts +1 -0
- package/src/internal/hardhat-network/provider/node.ts +110 -6
- package/src/internal/hardhat-network/provider/provider.ts +2 -0
- package/src/internal/hardhat-network/provider/utils/makeCommon.ts +9 -1
- package/src/internal/hardhat-network/stack-traces/vm-debug-tracer.ts +12 -10
- package/src/internal/solidity/dependencyGraph.ts +15 -3
- package/src/internal/solidity/resolver.ts +58 -16
- package/src/types/config.ts +2 -0
- package/src/utils/contract-names.ts +1 -0
- package/src/utils/remappings.ts +17 -0
- package/types/config.d.ts +2 -0
- package/types/config.d.ts.map +1 -1
- package/utils/contract-names.d.ts +1 -0
- package/utils/contract-names.d.ts.map +1 -1
- package/utils/contract-names.js +1 -0
- package/utils/contract-names.js.map +1 -1
- package/utils/remappings.d.ts +2 -0
- package/utils/remappings.d.ts.map +1 -0
- package/utils/remappings.js +15 -0
- package/utils/remappings.js.map +1 -0
|
@@ -315,7 +315,7 @@ async function createPackageJson() {
|
|
|
315
315
|
function showStarOnGitHubMessage() {
|
|
316
316
|
console.log(
|
|
317
317
|
chalk.cyan("Give Hardhat a star on Github if you're enjoying it!") +
|
|
318
|
-
emoji("
|
|
318
|
+
emoji(" ⭐️✨")
|
|
319
319
|
);
|
|
320
320
|
console.log();
|
|
321
321
|
console.log(chalk.cyan(" https://github.com/NomicFoundation/hardhat"));
|
|
@@ -278,6 +278,16 @@ Rename the file to use the .cjs to fix this problem.`,
|
|
|
278
278
|
To initialize the provider, make sure you first call \`.init()\` or any method that hits a node like request, send or sendAsync.`,
|
|
279
279
|
shouldBeReported: true,
|
|
280
280
|
},
|
|
281
|
+
INVALID_READ_OF_DIRECTORY: {
|
|
282
|
+
number: 22,
|
|
283
|
+
message:
|
|
284
|
+
"Invalid file path %absolutePath%. Attempting to read a directory instead of a file.",
|
|
285
|
+
title: "Invalid read: a directory cannot be read",
|
|
286
|
+
description: `An attempt was made to read a file, but a path to a directory was provided.
|
|
287
|
+
|
|
288
|
+
Please double check the file path.`,
|
|
289
|
+
shouldBeReported: false,
|
|
290
|
+
},
|
|
281
291
|
},
|
|
282
292
|
NETWORK: {
|
|
283
293
|
CONFIG_NOT_FOUND: {
|
|
@@ -585,6 +595,14 @@ Please double check your task definitions.`,
|
|
|
585
595
|
What makes these types special is that they can be represented as strings, so you can write them down in the terminal.`,
|
|
586
596
|
shouldBeReported: false,
|
|
587
597
|
},
|
|
598
|
+
DEPRECATED_TRANSFORM_IMPORT_TASK: {
|
|
599
|
+
number: 213,
|
|
600
|
+
title: "Use of deprecated remapping task",
|
|
601
|
+
message:
|
|
602
|
+
"Task TASK_COMPILE_TRANSFORM_IMPORT_NAME is deprecated. Please update your @nomicfoundation/hardhat-foundry plugin version.",
|
|
603
|
+
description: `This task has been deprecated in favor of a new approach.`,
|
|
604
|
+
shouldBeReported: true,
|
|
605
|
+
},
|
|
588
606
|
},
|
|
589
607
|
ARGUMENTS: {
|
|
590
608
|
INVALID_ENV_VAR_VALUE: {
|
|
@@ -855,6 +873,26 @@ Use a relative import instead of referencing the package's name.`,
|
|
|
855
873
|
Please double check your imports and installed libraries.`,
|
|
856
874
|
shouldBeReported: false,
|
|
857
875
|
},
|
|
876
|
+
INVALID_IMPORT_OF_DIRECTORY: {
|
|
877
|
+
number: 414,
|
|
878
|
+
message:
|
|
879
|
+
"Invalid import %imported% from %from%. Attempting to import a directory. Directories cannot be imported.",
|
|
880
|
+
title: "Invalid import: a directory cannot be imported",
|
|
881
|
+
description: `A Solidity file is attempting to import a directory, which is not possible.
|
|
882
|
+
|
|
883
|
+
Please double check your imports.`,
|
|
884
|
+
shouldBeReported: false,
|
|
885
|
+
},
|
|
886
|
+
AMBIGUOUS_SOURCE_NAMES: {
|
|
887
|
+
number: 415,
|
|
888
|
+
message:
|
|
889
|
+
"Two different source names (%sourcenames%) resolve to the same file (%file%).",
|
|
890
|
+
title: "Ambiguous source names",
|
|
891
|
+
description: `Two different source names map to the same file.
|
|
892
|
+
|
|
893
|
+
This is probably caused by multiple remappings pointing to the same source file.`,
|
|
894
|
+
shouldBeReported: false,
|
|
895
|
+
},
|
|
858
896
|
},
|
|
859
897
|
SOLC: {
|
|
860
898
|
INVALID_VERSION: {
|
|
@@ -40,6 +40,17 @@ export const rpcStorageSlot = new t.Type<bigint>(
|
|
|
40
40
|
t.identity
|
|
41
41
|
);
|
|
42
42
|
|
|
43
|
+
// This type is necessary because objects' keys need to be either strings or numbers to be properly handled by the 'io-ts' module.
|
|
44
|
+
// If they are not defined as strings or numbers, the type definition will result in an empty object without the required properties.
|
|
45
|
+
// For example, instead of displaying { ke1: value1 }, it will display {}
|
|
46
|
+
export const rpcStorageSlotHexString = new t.Type<string>(
|
|
47
|
+
"Storage slot hex string",
|
|
48
|
+
(x): x is string => typeof x === "string",
|
|
49
|
+
(u, c) =>
|
|
50
|
+
validateRpcStorageSlotHexString(u) ? t.success(u) : t.failure(u, c),
|
|
51
|
+
t.identity
|
|
52
|
+
);
|
|
53
|
+
|
|
43
54
|
function validateStorageSlot(u: unknown, c: t.Context): t.Validation<bigint> {
|
|
44
55
|
if (typeof u !== "string") {
|
|
45
56
|
return t.failure(
|
|
@@ -185,6 +196,10 @@ export function rpcDataToBuffer(data: string): Buffer {
|
|
|
185
196
|
|
|
186
197
|
// Type guards
|
|
187
198
|
|
|
199
|
+
function validateRpcStorageSlotHexString(u: unknown): u is string {
|
|
200
|
+
return typeof u === "string" && /^0x([0-9a-fA-F]){64}$/.test(u);
|
|
201
|
+
}
|
|
202
|
+
|
|
188
203
|
function isRpcQuantityString(u: unknown): u is string {
|
|
189
204
|
return (
|
|
190
205
|
typeof u === "string" &&
|
|
@@ -2,7 +2,14 @@ import * as t from "io-ts";
|
|
|
2
2
|
|
|
3
3
|
import { optionalOrNullable } from "../../../../util/io-ts";
|
|
4
4
|
import { rpcAccessList } from "../access-list";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
rpcAddress,
|
|
7
|
+
rpcData,
|
|
8
|
+
rpcQuantity,
|
|
9
|
+
rpcStorageSlot,
|
|
10
|
+
rpcStorageSlotHexString,
|
|
11
|
+
} from "../base-types";
|
|
12
|
+
import { address } from "../../../config/config-validation";
|
|
6
13
|
|
|
7
14
|
// Type used by eth_call and eth_estimateGas
|
|
8
15
|
export const rpcCallRequest = t.type(
|
|
@@ -21,3 +28,30 @@ export const rpcCallRequest = t.type(
|
|
|
21
28
|
);
|
|
22
29
|
|
|
23
30
|
export type RpcCallRequest = t.TypeOf<typeof rpcCallRequest>;
|
|
31
|
+
|
|
32
|
+
// Types used by eth_call to configure the state override set
|
|
33
|
+
export const stateProperties = t.record(
|
|
34
|
+
rpcStorageSlotHexString,
|
|
35
|
+
rpcStorageSlot
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
export const stateOverrideOptions = t.type(
|
|
39
|
+
{
|
|
40
|
+
balance: optionalOrNullable(rpcQuantity),
|
|
41
|
+
nonce: optionalOrNullable(rpcQuantity),
|
|
42
|
+
code: optionalOrNullable(rpcData),
|
|
43
|
+
state: optionalOrNullable(stateProperties),
|
|
44
|
+
stateDiff: optionalOrNullable(stateProperties),
|
|
45
|
+
},
|
|
46
|
+
"stateOverrideOptions"
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export const stateOverrideSet = t.record(address, stateOverrideOptions);
|
|
50
|
+
export const optionalStateOverrideSet = optionalOrNullable(stateOverrideSet);
|
|
51
|
+
|
|
52
|
+
export type StateProperties = t.TypeOf<typeof stateProperties>;
|
|
53
|
+
export type StateOverrideOptions = t.TypeOf<typeof stateOverrideOptions>;
|
|
54
|
+
export type StateOverrideSet = t.TypeOf<typeof stateOverrideSet>;
|
|
55
|
+
export type OptionalStateOverrideSet = t.TypeOf<
|
|
56
|
+
typeof optionalStateOverrideSet
|
|
57
|
+
>;
|
|
@@ -116,6 +116,8 @@ export async function createProvider(
|
|
|
116
116
|
forkConfig,
|
|
117
117
|
forkCachePath:
|
|
118
118
|
paths !== undefined ? getForkCacheDirPath(paths) : undefined,
|
|
119
|
+
enableTransientStorage:
|
|
120
|
+
hardhatNetConfig.enableTransientStorage ?? false,
|
|
119
121
|
},
|
|
120
122
|
new ModulesLogger(hardhatNetConfig.loggingEnabled),
|
|
121
123
|
artifacts
|
|
@@ -348,10 +348,30 @@ export class ForkBlockchain
|
|
|
348
348
|
return undefined;
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
351
|
+
let transaction: TypedTransaction;
|
|
352
|
+
|
|
353
|
+
if (rpcTransaction.type === undefined || rpcTransaction.type === 0n) {
|
|
354
|
+
transaction = new ReadOnlyValidTransaction(
|
|
355
|
+
new Address(rpcTransaction.from),
|
|
356
|
+
rpcToTxData(rpcTransaction)
|
|
357
|
+
);
|
|
358
|
+
} else if (rpcTransaction.type === 1n) {
|
|
359
|
+
transaction = new ReadOnlyValidEIP2930Transaction(
|
|
360
|
+
new Address(rpcTransaction.from),
|
|
361
|
+
rpcToTxData(rpcTransaction)
|
|
362
|
+
);
|
|
363
|
+
} else if (rpcTransaction.type === 2n) {
|
|
364
|
+
transaction = new ReadOnlyValidEIP1559Transaction(
|
|
365
|
+
new Address(rpcTransaction.from),
|
|
366
|
+
rpcToTxData(rpcTransaction) as FeeMarketEIP1559TxData
|
|
367
|
+
);
|
|
368
|
+
} else {
|
|
369
|
+
transaction = new ReadOnlyValidUnknownTypeTransaction(
|
|
370
|
+
new Address(rpcTransaction.from),
|
|
371
|
+
Number(rpcTransaction.type),
|
|
372
|
+
rpcToTxData(rpcTransaction)
|
|
373
|
+
);
|
|
374
|
+
}
|
|
355
375
|
|
|
356
376
|
this._data.addTransaction(transaction);
|
|
357
377
|
|
|
@@ -37,6 +37,8 @@ import {
|
|
|
37
37
|
RpcOldBlockTag,
|
|
38
38
|
} from "../../../core/jsonrpc/types/input/blockTag";
|
|
39
39
|
import {
|
|
40
|
+
optionalStateOverrideSet,
|
|
41
|
+
OptionalStateOverrideSet,
|
|
40
42
|
rpcCallRequest,
|
|
41
43
|
RpcCallRequest,
|
|
42
44
|
} from "../../../core/jsonrpc/types/input/callRequest";
|
|
@@ -334,13 +336,21 @@ export class EthModule {
|
|
|
334
336
|
|
|
335
337
|
// eth_call
|
|
336
338
|
|
|
337
|
-
private _callParams(
|
|
338
|
-
|
|
339
|
+
private _callParams(
|
|
340
|
+
params: any[]
|
|
341
|
+
): [RpcCallRequest, OptionalRpcNewBlockTag, OptionalStateOverrideSet] {
|
|
342
|
+
return validateParams(
|
|
343
|
+
params,
|
|
344
|
+
rpcCallRequest,
|
|
345
|
+
optionalRpcNewBlockTag,
|
|
346
|
+
optionalStateOverrideSet
|
|
347
|
+
);
|
|
339
348
|
}
|
|
340
349
|
|
|
341
350
|
private async _callAction(
|
|
342
351
|
rpcCall: RpcCallRequest,
|
|
343
|
-
blockTag: OptionalRpcNewBlockTag
|
|
352
|
+
blockTag: OptionalRpcNewBlockTag,
|
|
353
|
+
stateOverrideSet: OptionalStateOverrideSet
|
|
344
354
|
): Promise<string> {
|
|
345
355
|
this._validateTransactionAndCallRequest(rpcCall);
|
|
346
356
|
|
|
@@ -353,7 +363,11 @@ export class EthModule {
|
|
|
353
363
|
trace,
|
|
354
364
|
error,
|
|
355
365
|
consoleLogMessages,
|
|
356
|
-
} = await this._node.runCall(
|
|
366
|
+
} = await this._node.runCall(
|
|
367
|
+
callParams,
|
|
368
|
+
blockNumberOrPending,
|
|
369
|
+
stateOverrideSet
|
|
370
|
+
);
|
|
357
371
|
|
|
358
372
|
const code = await this._node.getCodeFromTrace(trace, blockNumberOrPending);
|
|
359
373
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Block, HeaderData } from "@nomicfoundation/ethereumjs-block";
|
|
2
|
-
import { Common } from "@nomicfoundation/ethereumjs-common";
|
|
2
|
+
import { Common, CustomCommonOpts } from "@nomicfoundation/ethereumjs-common";
|
|
3
3
|
import {
|
|
4
4
|
AccessListEIP2930Transaction,
|
|
5
5
|
FeeMarketEIP1559Transaction,
|
|
@@ -83,6 +83,10 @@ import { VMTracer } from "../stack-traces/vm-tracer";
|
|
|
83
83
|
import "./ethereumjs-workarounds";
|
|
84
84
|
import { rpcQuantityToBigInt } from "../../core/jsonrpc/types/base-types";
|
|
85
85
|
import { JsonRpcClient } from "../jsonrpc/client";
|
|
86
|
+
import {
|
|
87
|
+
StateOverrideSet,
|
|
88
|
+
StateProperties,
|
|
89
|
+
} from "../../core/jsonrpc/types/input/callRequest";
|
|
86
90
|
import { bloomFilter, Filter, filterLogs, LATEST_BLOCK, Type } from "./filter";
|
|
87
91
|
import { ForkBlockchain } from "./fork/ForkBlockchain";
|
|
88
92
|
import { ForkStateManager } from "./fork/ForkStateManager";
|
|
@@ -146,6 +150,7 @@ export class HardhatNode extends EventEmitter {
|
|
|
146
150
|
networkId,
|
|
147
151
|
chainId,
|
|
148
152
|
allowBlocksWithSameTimestamp,
|
|
153
|
+
enableTransientStorage,
|
|
149
154
|
} = config;
|
|
150
155
|
|
|
151
156
|
const allowUnlimitedContractSize =
|
|
@@ -303,7 +308,8 @@ export class HardhatNode extends EventEmitter {
|
|
|
303
308
|
forkBlockNum,
|
|
304
309
|
forkBlockHash,
|
|
305
310
|
nextBlockBaseFeePerGas,
|
|
306
|
-
forkClient
|
|
311
|
+
forkClient,
|
|
312
|
+
enableTransientStorage
|
|
307
313
|
);
|
|
308
314
|
|
|
309
315
|
return [common, node];
|
|
@@ -390,7 +396,8 @@ Hardhat Network's forking functionality only works with blocks from at least spu
|
|
|
390
396
|
private _forkBlockNumber?: bigint,
|
|
391
397
|
private _forkBlockHash?: string,
|
|
392
398
|
nextBlockBaseFee?: bigint,
|
|
393
|
-
private _forkClient?: JsonRpcClient
|
|
399
|
+
private _forkClient?: JsonRpcClient,
|
|
400
|
+
private readonly _enableTransientStorage: boolean = false
|
|
394
401
|
) {
|
|
395
402
|
super();
|
|
396
403
|
|
|
@@ -624,7 +631,8 @@ Hardhat Network's forking functionality only works with blocks from at least spu
|
|
|
624
631
|
|
|
625
632
|
public async runCall(
|
|
626
633
|
call: CallParams,
|
|
627
|
-
blockNumberOrPending: bigint | "pending"
|
|
634
|
+
blockNumberOrPending: bigint | "pending",
|
|
635
|
+
stateOverrideSet: StateOverrideSet = {}
|
|
628
636
|
): Promise<RunCallResult> {
|
|
629
637
|
let txParams: TransactionParams;
|
|
630
638
|
|
|
@@ -659,7 +667,13 @@ Hardhat Network's forking functionality only works with blocks from at least spu
|
|
|
659
667
|
|
|
660
668
|
const result = await this._runInBlockContext(
|
|
661
669
|
blockNumberOrPending,
|
|
662
|
-
async () =>
|
|
670
|
+
async () =>
|
|
671
|
+
this._runTxAndRevertMutations(
|
|
672
|
+
tx,
|
|
673
|
+
blockNumberOrPending,
|
|
674
|
+
true,
|
|
675
|
+
stateOverrideSet
|
|
676
|
+
)
|
|
663
677
|
);
|
|
664
678
|
|
|
665
679
|
const traces = await this._gatherTraces(result.execResult);
|
|
@@ -2354,6 +2368,83 @@ Hardhat Network's forking functionality only works with blocks from at least spu
|
|
|
2354
2368
|
);
|
|
2355
2369
|
}
|
|
2356
2370
|
|
|
2371
|
+
private async _applyStateOverrideSet(stateOverrideSet: StateOverrideSet) {
|
|
2372
|
+
// Multiple state override set can be configured for different addresses, hence the loop
|
|
2373
|
+
for (const [addrToOverride, stateOverrideOptions] of Object.entries(
|
|
2374
|
+
stateOverrideSet
|
|
2375
|
+
)) {
|
|
2376
|
+
const address = new Address(toBuffer(addrToOverride));
|
|
2377
|
+
|
|
2378
|
+
const { balance, nonce, code, state, stateDiff } = stateOverrideOptions;
|
|
2379
|
+
|
|
2380
|
+
await this._overrideBalanceAndNonce(address, balance, nonce);
|
|
2381
|
+
await this._overrideCode(address, code);
|
|
2382
|
+
await this._overrideStateAndStateDiff(address, state, stateDiff);
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
private async _overrideBalanceAndNonce(
|
|
2387
|
+
address: Address,
|
|
2388
|
+
balance: bigint | undefined,
|
|
2389
|
+
nonce: bigint | undefined
|
|
2390
|
+
) {
|
|
2391
|
+
const MAX_NONCE = 2n ** 64n - 1n;
|
|
2392
|
+
const MAX_BALANCE = 2n ** 256n - 1n;
|
|
2393
|
+
|
|
2394
|
+
if (nonce !== undefined && nonce > MAX_NONCE) {
|
|
2395
|
+
throw new InvalidInputError(
|
|
2396
|
+
`The 'nonce' property should occupy a maximum of 8 bytes (nonce=${nonce}).`
|
|
2397
|
+
);
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
if (balance !== undefined && balance > MAX_BALANCE) {
|
|
2401
|
+
throw new InvalidInputError(
|
|
2402
|
+
`The 'balance' property should occupy a maximum of 32 bytes (balance=${balance}).`
|
|
2403
|
+
);
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
await this._stateManager.modifyAccountFields(address, {
|
|
2407
|
+
balance,
|
|
2408
|
+
nonce,
|
|
2409
|
+
});
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2412
|
+
private async _overrideCode(address: Address, code: Buffer | undefined) {
|
|
2413
|
+
if (code === undefined) return;
|
|
2414
|
+
|
|
2415
|
+
await this._stateManager.putContractCode(address, code);
|
|
2416
|
+
}
|
|
2417
|
+
|
|
2418
|
+
private async _overrideStateAndStateDiff(
|
|
2419
|
+
address: Address,
|
|
2420
|
+
state: StateProperties | undefined,
|
|
2421
|
+
stateDiff: StateProperties | undefined
|
|
2422
|
+
) {
|
|
2423
|
+
let newState;
|
|
2424
|
+
|
|
2425
|
+
if (state !== undefined && stateDiff === undefined) {
|
|
2426
|
+
await this._stateManager.clearContractStorage(address);
|
|
2427
|
+
newState = state;
|
|
2428
|
+
} else if (state === undefined && stateDiff !== undefined) {
|
|
2429
|
+
newState = stateDiff;
|
|
2430
|
+
} else if (state === undefined && stateDiff === undefined) {
|
|
2431
|
+
// nothing to do
|
|
2432
|
+
return;
|
|
2433
|
+
} else {
|
|
2434
|
+
throw new InvalidInputError(
|
|
2435
|
+
"The properties 'state' and 'stateDiff' cannot be used simultaneously when configuring the state override set passed to the eth_call method."
|
|
2436
|
+
);
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
for (const [storageKey, value] of Object.entries(newState)) {
|
|
2440
|
+
await this._stateManager.putContractStorage(
|
|
2441
|
+
address,
|
|
2442
|
+
toBuffer(storageKey),
|
|
2443
|
+
setLengthLeft(bigIntToBuffer(value), 32)
|
|
2444
|
+
);
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2357
2448
|
/**
|
|
2358
2449
|
* This function runs a transaction and reverts all the modifications that it
|
|
2359
2450
|
* makes.
|
|
@@ -2361,10 +2452,13 @@ Hardhat Network's forking functionality only works with blocks from at least spu
|
|
|
2361
2452
|
private async _runTxAndRevertMutations(
|
|
2362
2453
|
tx: TypedTransaction,
|
|
2363
2454
|
blockNumberOrPending: bigint | "pending",
|
|
2364
|
-
forceBaseFeeZero = false
|
|
2455
|
+
forceBaseFeeZero = false,
|
|
2456
|
+
stateOverrideSet: StateOverrideSet = {}
|
|
2365
2457
|
): Promise<RunTxResult> {
|
|
2366
2458
|
const initialStateRoot = await this._stateManager.getStateRoot();
|
|
2367
2459
|
|
|
2460
|
+
await this._applyStateOverrideSet(stateOverrideSet);
|
|
2461
|
+
|
|
2368
2462
|
let blockContext: Block | undefined;
|
|
2369
2463
|
let originalCommon: Common | undefined;
|
|
2370
2464
|
|
|
@@ -2400,6 +2494,7 @@ Hardhat Network's forking functionality only works with blocks from at least spu
|
|
|
2400
2494
|
},
|
|
2401
2495
|
{
|
|
2402
2496
|
hardfork: this._selectHardfork(blockContext.header.number),
|
|
2497
|
+
...this._getTransientStorageSettings(),
|
|
2403
2498
|
}
|
|
2404
2499
|
);
|
|
2405
2500
|
|
|
@@ -2740,6 +2835,7 @@ Hardhat Network's forking functionality only works with blocks from at least spu
|
|
|
2740
2835
|
},
|
|
2741
2836
|
{
|
|
2742
2837
|
hardfork: this._selectHardfork(BigInt(blockNumber)),
|
|
2838
|
+
...this._getTransientStorageSettings(),
|
|
2743
2839
|
}
|
|
2744
2840
|
);
|
|
2745
2841
|
|
|
@@ -2750,4 +2846,12 @@ Hardhat Network's forking functionality only works with blocks from at least spu
|
|
|
2750
2846
|
);
|
|
2751
2847
|
}
|
|
2752
2848
|
}
|
|
2849
|
+
|
|
2850
|
+
private _getTransientStorageSettings(): Partial<CustomCommonOpts> {
|
|
2851
|
+
if (this._enableTransientStorage) {
|
|
2852
|
+
return { eips: [1153] };
|
|
2853
|
+
}
|
|
2854
|
+
|
|
2855
|
+
return {};
|
|
2856
|
+
}
|
|
2753
2857
|
}
|
|
@@ -80,6 +80,7 @@ interface HardhatNetworkProviderConfig {
|
|
|
80
80
|
experimentalHardhatNetworkMessageTraceHooks?: BoundExperimentalHardhatNetworkMessageTraceHook[];
|
|
81
81
|
forkConfig?: ForkConfig;
|
|
82
82
|
forkCachePath?: string;
|
|
83
|
+
enableTransientStorage: boolean;
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
export class HardhatNetworkProvider
|
|
@@ -253,6 +254,7 @@ export class HardhatNetworkProvider
|
|
|
253
254
|
coinbase: this._config.coinbase ?? DEFAULT_COINBASE,
|
|
254
255
|
chains: this._config.chains,
|
|
255
256
|
allowBlocksWithSameTimestamp: this._config.allowBlocksWithSameTimestamp,
|
|
257
|
+
enableTransientStorage: this._config.enableTransientStorage,
|
|
256
258
|
};
|
|
257
259
|
|
|
258
260
|
const [common, node] = await HardhatNode.create(config);
|
|
@@ -2,7 +2,14 @@ import { Common } from "@nomicfoundation/ethereumjs-common";
|
|
|
2
2
|
|
|
3
3
|
import { LocalNodeConfig } from "../node-types";
|
|
4
4
|
|
|
5
|
-
export function makeCommon({
|
|
5
|
+
export function makeCommon({
|
|
6
|
+
chainId,
|
|
7
|
+
networkId,
|
|
8
|
+
hardfork,
|
|
9
|
+
enableTransientStorage,
|
|
10
|
+
}: LocalNodeConfig) {
|
|
11
|
+
const otherSettings = enableTransientStorage ? { eips: [1153] } : {};
|
|
12
|
+
|
|
6
13
|
const common = Common.custom(
|
|
7
14
|
{
|
|
8
15
|
chainId,
|
|
@@ -10,6 +17,7 @@ export function makeCommon({ chainId, networkId, hardfork }: LocalNodeConfig) {
|
|
|
10
17
|
},
|
|
11
18
|
{
|
|
12
19
|
hardfork,
|
|
20
|
+
...otherSettings,
|
|
13
21
|
}
|
|
14
22
|
);
|
|
15
23
|
|
|
@@ -280,10 +280,12 @@ export class VMDebugTracer {
|
|
|
280
280
|
"There shouldn't be two messages one after another"
|
|
281
281
|
);
|
|
282
282
|
|
|
283
|
-
//
|
|
284
|
-
//
|
|
285
|
-
|
|
286
|
-
|
|
283
|
+
// memory opcodes reflect the expanded memory in that step,
|
|
284
|
+
// so we correct them
|
|
285
|
+
if (
|
|
286
|
+
previousStructLog.op === "MSTORE" ||
|
|
287
|
+
previousStructLog.op === "MLOAD"
|
|
288
|
+
) {
|
|
287
289
|
const memoryLengthDifference =
|
|
288
290
|
structLog.memory.length - previousStructLog.memory.length;
|
|
289
291
|
for (let k = 0; k < memoryLengthDifference; k++) {
|
|
@@ -315,13 +317,13 @@ export class VMDebugTracer {
|
|
|
315
317
|
}
|
|
316
318
|
|
|
317
319
|
private _getMemory(step: InterpreterStep): string[] {
|
|
318
|
-
const
|
|
319
|
-
.
|
|
320
|
-
|
|
320
|
+
const rawMemory =
|
|
321
|
+
Buffer.from(step.memory)
|
|
322
|
+
.toString("hex")
|
|
323
|
+
.match(/.{1,64}/g) ?? [];
|
|
321
324
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
return result;
|
|
325
|
+
// Remove the additional non allocated memory
|
|
326
|
+
return rawMemory.slice(0, Number(step.memoryWordCount));
|
|
325
327
|
}
|
|
326
328
|
|
|
327
329
|
private _getStack(step: InterpreterStep): string[] {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as taskTypes from "../../types/builtin-tasks";
|
|
2
|
+
import { HardhatError } from "../core/errors";
|
|
3
|
+
import { ERRORS } from "../core/errors-list";
|
|
2
4
|
|
|
3
5
|
import { ResolvedFile, Resolver } from "./resolver";
|
|
4
6
|
|
|
@@ -22,7 +24,8 @@ export class DependencyGraph implements taskTypes.DependencyGraph {
|
|
|
22
24
|
private _resolvedFiles = new Map<string, ResolvedFile>();
|
|
23
25
|
private _dependenciesPerFile = new Map<string, Set<ResolvedFile>>();
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
// map absolute paths to source names
|
|
28
|
+
private readonly _visitedFiles = new Map<string, string>();
|
|
26
29
|
|
|
27
30
|
private constructor() {}
|
|
28
31
|
|
|
@@ -160,11 +163,20 @@ export class DependencyGraph implements taskTypes.DependencyGraph {
|
|
|
160
163
|
resolver: Resolver,
|
|
161
164
|
file: ResolvedFile
|
|
162
165
|
): Promise<void> {
|
|
163
|
-
|
|
166
|
+
const sourceName = this._visitedFiles.get(file.absolutePath);
|
|
167
|
+
|
|
168
|
+
if (sourceName !== undefined) {
|
|
169
|
+
if (sourceName !== file.sourceName) {
|
|
170
|
+
throw new HardhatError(ERRORS.RESOLVER.AMBIGUOUS_SOURCE_NAMES, {
|
|
171
|
+
sourcenames: `'${sourceName}' and '${file.sourceName}'`,
|
|
172
|
+
file: file.absolutePath,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
164
176
|
return;
|
|
165
177
|
}
|
|
166
178
|
|
|
167
|
-
this._visitedFiles.
|
|
179
|
+
this._visitedFiles.set(file.absolutePath, file.sourceName);
|
|
168
180
|
|
|
169
181
|
const dependencies = new Set<ResolvedFile>();
|
|
170
182
|
this._resolvedFiles.set(file.sourceName, file);
|