Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/src/content/hardhat-network/docs/reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- merge
- shanghai
- cancun
- prague

## Config

Expand Down Expand Up @@ -66,7 +67,7 @@ The block gas limit to use in Hardhat Network's blockchain. Default value: `30_0

#### `hardfork`

This setting changes how Hardhat Network works, to mimic Ethereum's mainnet at a given hardfork. It must be one of `"byzantium"`, `"constantinople"`, `"petersburg"`, `"istanbul"`, `"muirGlacier"`, `"berlin"`, `"london"`, `"arrowGlacier"`, `"grayGlacier"`, `"merge"`, `"shanghai"` and `"cancun"`. Default value: `"cancun"`
This setting changes how Hardhat Network works, to mimic Ethereum's mainnet at a given hardfork. It must be one of `"byzantium"`, `"constantinople"`, `"petersburg"`, `"istanbul"`, `"muirGlacier"`, `"berlin"`, `"london"`, `"arrowGlacier"`, `"grayGlacier"`, `"merge"`, `"shanghai"`, `"cancun"` and `"prague"`. Default value: `"prague"`

#### `throwOnTransactionFailures`

Expand Down
8 changes: 3 additions & 5 deletions packages/hardhat-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
"devDependencies": {
"@nomicfoundation/eslint-plugin-hardhat-internal-rules": "workspace:^",
"@nomicfoundation/eslint-plugin-slow-imports": "workspace:^",
"@nomicfoundation/ethereumjs-block": "5.0.4",
"@types/async-eventemitter": "^0.2.1",
"@types/bn.js": "^5.1.0",
"@types/chai": "^4.2.0",
Expand Down Expand Up @@ -98,12 +97,12 @@
"typescript": "~5.0.0"
},
"dependencies": {
"@ethereumjs/common": "^4.4.0",
"@ethereumjs/tx": "^5.4.0",
"@ethereumjs/util": "^9.1.0",
"@ethersproject/abi": "^5.1.2",
"@metamask/eth-sig-util": "^4.0.0",
"@nomicfoundation/edr": "^0.8.0",
"@nomicfoundation/ethereumjs-common": "4.0.4",
"@nomicfoundation/ethereumjs-tx": "5.0.4",
"@nomicfoundation/ethereumjs-util": "9.0.4",
"@nomicfoundation/solidity-analyzer": "^0.1.0",
"@sentry/node": "^5.18.1",
"@types/bn.js": "^5.1.0",
Expand All @@ -118,7 +117,6 @@
"enquirer": "^2.3.0",
"env-paths": "^2.2.0",
"ethereum-cryptography": "^1.0.3",
"ethereumjs-abi": "^0.6.8",
"find-up": "^5.0.0",
"fp-ts": "1.19.3",
"fs-extra": "^7.0.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/hardhat-core/src/builtin-tasks/node.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type EthereumjsUtilT from "@nomicfoundation/ethereumjs-util";
import type EthereumjsUtilT from "@ethereumjs/util";

import picocolors from "picocolors";
import debug from "debug";
Expand Down Expand Up @@ -56,7 +56,7 @@ function logHardhatNetworkAccounts(networkConfig: HardhatNetworkConfig) {
privateToAddress,
toBytes,
toChecksumAddress,
} = require("@nomicfoundation/ethereumjs-util") as typeof EthereumjsUtilT;
} = require("@ethereumjs/util") as typeof EthereumjsUtilT;

console.log("Accounts");
console.log("========");
Expand Down
1 change: 1 addition & 0 deletions packages/hardhat-core/src/internal/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const HARDHAT_NETWORK_SUPPORTED_HARDFORKS = [
"merge",
"shanghai",
"cancun",
"prague",
];

export const HARDHAT_MEMPOOL_SUPPORTED_ORDERS = ["fifo", "priority"] as const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,19 +238,6 @@ function resolveHardhatNetworkConfig(
delete config.initialBaseFeePerGas;
}

if (
hardhatNetworkConfig.enableTransientStorage === true &&
hardhatNetworkConfig.hardfork === undefined
) {
config.hardfork = "cancun";
}
if (
hardhatNetworkConfig.enableTransientStorage === false &&
hardhatNetworkConfig.hardfork === undefined
) {
config.hardfork = "shanghai";
}

return config;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const defaultHardhatNetworkParams: Omit<
HardhatNetworkConfig,
"gas" | "initialDate"
> = {
hardfork: HardforkName.CANCUN,
hardfork: HardforkName.PRAGUE,
blockGasLimit: 30_000_000,
gasPrice: HARDHAT_NETWORK_DEFAULT_GAS_PRICE,
chainId: 31337,
Expand All @@ -56,7 +56,7 @@ export const defaultHardhatNetworkParams: Omit<
minGasPrice: 0n,
chains: new Map([
[
// block numbers below were taken from https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/common/src/chains
// block numbers below were taken from https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/common/src/chains.ts
1, // mainnet
{
hardforkHistory: new Map([
Expand All @@ -77,6 +77,7 @@ export const defaultHardhatNetworkParams: Omit<
[HardforkName.MERGE, 15_537_394],
[HardforkName.SHANGHAI, 17_034_870],
[HardforkName.CANCUN, 19_426_589],
[HardforkName.PRAGUE, 30_000_000], // TODO: replace with actual block number
]),
},
],
Expand Down Expand Up @@ -138,6 +139,7 @@ export const defaultHardhatNetworkParams: Omit<
[HardforkName.MERGE, 1_450_409],
[HardforkName.SHANGHAI, 2_990_908],
[HardforkName.CANCUN, 5_187_023],
[HardforkName.PRAGUE, 30_000_000], // TODO: replace with actual block number
]),
},
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as t from "io-ts";

import { rpcAddress, rpcQuantity, rpcHash, rpcParity } from "./base-types";

const rpcAuthorizationListTuple = t.type({
chainId: rpcQuantity,
address: rpcAddress,
nonce: rpcQuantity,
yParity: rpcParity,
r: rpcHash,
s: rpcHash,
});

export const rpcAuthorizationList = t.array(rpcAuthorizationListTuple);

export type RpcAuthorizationListTuple = t.TypeOf<
typeof rpcAuthorizationListTuple
>;

export type RpcAuthorizationList = t.TypeOf<typeof rpcAuthorizationList>;
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
bytesToHex as bufferToHex,
isValidAddress,
toBytes,
} from "@nomicfoundation/ethereumjs-util";
} from "@ethereumjs/util";
import * as t from "io-ts";

import * as BigIntUtils from "../../../util/bigint";
Expand All @@ -27,6 +27,14 @@ export const rpcData = new t.Type<Buffer>(
t.identity
);

export const rpcParity = new t.Type<Buffer>(
"PARITY",
Buffer.isBuffer,
(u, c) =>
isRpcParityString(u) ? t.success(Buffer.from(toBytes(u))) : t.failure(u, c),
t.identity
);

export const rpcHash = new t.Type<Buffer>(
"HASH",
(v): v is Buffer => Buffer.isBuffer(v) && v.length === HASH_LENGTH_BYTES,
Expand Down Expand Up @@ -216,6 +224,10 @@ function isRpcDataString(u: unknown): u is string {
return typeof u === "string" && u.match(/^0x(?:[0-9a-fA-F]{2})*$/) !== null;
}

function isRpcParityString(u: unknown): u is string {
return typeof u === "string" && u.match(/^0x[0-9a-fA-F]{1,2}$/) !== null;
}

function isRpcHashString(u: unknown): u is string {
return typeof u === "string" && u.length === 66 && isRpcDataString(u);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as t from "io-ts";
import { optionalOrNullable } from "../../../../util/io-ts";
import { rpcAccessList } from "../access-list";
import { rpcAddress, rpcData, rpcHash, rpcQuantity } from "../base-types";
import { rpcAuthorizationList } from "../authorization-list";

// Type used by eth_sendTransaction
export const rpcTransactionRequest = t.type(
Expand All @@ -20,6 +21,7 @@ export const rpcTransactionRequest = t.type(
maxPriorityFeePerGas: optionalOrNullable(rpcQuantity),
blobs: optionalOrNullable(t.array(rpcData)),
blobVersionedHashes: optionalOrNullable(t.array(rpcHash)),
authorizationList: optionalOrNullable(rpcAuthorizationList),
},
"RpcTransactionRequest"
);
Expand All @@ -42,6 +44,14 @@ export interface RpcTransactionRequestInput {
maxPriorityFeePerGas?: string;
blobs?: string[];
blobVersionedHashes?: string[];
authorizationList?: Array<{
chainId: string;
address: string;
nonce: string;
yParity: string;
r: string;
s: string;
}>;
}

export type RpcTransactionRequest = t.TypeOf<typeof rpcTransactionRequest>;
62 changes: 45 additions & 17 deletions packages/hardhat-core/src/internal/core/providers/accounts.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as t from "io-ts";

import { signTypedData, SignTypedDataVersion } from "@metamask/eth-sig-util";
import { FeeMarketEIP1559Transaction } from "@nomicfoundation/ethereumjs-tx";
import { FeeMarketEIP1559Transaction } from "@ethereumjs/tx";
import { EIP1193Provider, RequestArguments } from "../../../types";
import { HardhatError } from "../errors";
import { ERRORS } from "../errors-list";
Expand Down Expand Up @@ -49,7 +49,7 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {
toRpcSig,
toBytes,
bytesToHex: bufferToHex,
} = await import("@nomicfoundation/ethereumjs-util");
} = await import("@ethereumjs/util");

if (
args.method === "eth_accounts" ||
Expand Down Expand Up @@ -197,7 +197,7 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {
bytesToHex: bufferToHex,
toBytes,
privateToAddress,
} = require("@nomicfoundation/ethereumjs-util");
} = require("@ethereumjs/util");

const privateKeys: Buffer[] = localAccountsHexPrivateKeys.map((h) =>
toBytes(h)
Expand All @@ -210,9 +210,7 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {
}

private _getPrivateKeyForAddress(address: Buffer): Buffer {
const {
bytesToHex: bufferToHex,
} = require("@nomicfoundation/ethereumjs-util");
const { bytesToHex: bufferToHex } = require("@ethereumjs/util");
const pk = this._addressToPrivateKey.get(bufferToHex(address));
if (pk === undefined) {
throw new HardhatError(ERRORS.NETWORK.NOT_LOCAL_ACCOUNT, {
Expand All @@ -232,9 +230,7 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {
}

private async _getNonce(address: Buffer): Promise<bigint> {
const { bytesToHex: bufferToHex } = await import(
"@nomicfoundation/ethereumjs-util"
);
const { bytesToHex: bufferToHex } = await import("@ethereumjs/util");

const response = (await this._wrappedProvider.request({
method: "eth_getTransactionCount",
Expand All @@ -249,11 +245,15 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {
chainId: number,
privateKey: Buffer
): Promise<Uint8Array> {
const { AccessListEIP2930Transaction, LegacyTransaction } = await import(
"@nomicfoundation/ethereumjs-tx"
);
const {
AccessListEIP2930Transaction,
LegacyTransaction,
EOACodeEIP7702Transaction,
} = await import("@ethereumjs/tx");

const { Common } = await import("@nomicfoundation/ethereumjs-common");
const { Common } = await import("@ethereumjs/common");

const { toBytes } = await import("@ethereumjs/util");

const txData = {
...transactionRequest,
Expand All @@ -272,8 +272,38 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {
({ address, storageKeys }) => [address, storageKeys] as [Buffer, Buffer[]]
);

// we convert the authorization list to the type
// that EOACodeEIP7702Transaction expects
const authorizationList = txData.authorizationList?.map(
({ chainId: authChainId, address, nonce, yParity, r, s }) =>
// TODO: There is an error in the type definition of rpcAuthorizationList
// in the @ethereumjs/common@4.4.0 package where nonce is defined as an
// array but it should be a string. This is fixed in the alpha version
// of the package but is not yet released. To work around this, we wrap
// nonce in an array here. However, this will not be accepted by the
// node and will throw an error.
[
Buffer.from(toBytes(authChainId)),
address,
[Buffer.from(toBytes(nonce))],
yParity,
r,
s,
] as [Buffer, Buffer, Buffer[], Buffer, Buffer, Buffer]
);

let transaction;
if (txData.maxFeePerGas !== undefined) {
if (authorizationList !== undefined) {
transaction = EOACodeEIP7702Transaction.fromTxData(
{
...txData,
accessList,
authorizationList,
gasPrice: undefined,
},
{ common }
);
} else if (txData.maxFeePerGas !== undefined) {
transaction = FeeMarketEIP1559Transaction.fromTxData(
{
...txData,
Expand Down Expand Up @@ -320,9 +350,7 @@ export class HDWalletProvider extends LocalAccountsProvider {
passphrase
);

const {
bytesToHex: bufferToHex,
} = require("@nomicfoundation/ethereumjs-util");
const { bytesToHex: bufferToHex } = require("@ethereumjs/util");
const privateKeysAsHex = privateKeys.map((pk) => bufferToHex(pk));
super(provider, privateKeysAsHex);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/hardhat-core/src/internal/core/providers/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function normalizeHardhatNetworkAccountsConfig(
return accountsConfig;
}

const { bytesToHex } = require("@nomicfoundation/ethereumjs-util");
const { bytesToHex } = require("@ethereumjs/util");

return derivePrivateKeys(
accountsConfig.mnemonic,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import {
Address,
bytesToHex as bufferToHex,
} from "@nomicfoundation/ethereumjs-util";
import { Address, bytesToHex as bufferToHex } from "@ethereumjs/util";
import fsExtra from "fs-extra";
import * as t from "io-ts";
import path from "path";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export interface LegacyTransactionParams extends BaseTransactionParams {

export interface AccessListTransactionParams extends BaseTransactionParams {
gasPrice: bigint;
// We use this access list format because @nomicfoundation/ethereumjs-tx access list data
// We use this access list format because @ethereumjs/tx access list data
// forces us to use it or stringify them
accessList: AccessListBufferItem[];
// We don't include chainId as it's not necessary, the node
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export interface RpcBlockOutput {
export type RpcTransactionOutput =
| LegacyRpcTransactionOutput
| AccessListEIP2930RpcTransactionOutput
| EIP1559RpcTransactionOutput;
| EIP1559RpcTransactionOutput
| EOACodeEIP7702TransactionOutput;

interface BaseRpcTransactionOutput {
blockHash: string | null;
Expand Down Expand Up @@ -60,6 +61,15 @@ export type RpcAccessListOutput = Array<{
storageKeys: string[];
}>;

export type RpcAuthorizationListOutput = Array<{
chainId: string;
address: string;
nonce: string;
yParity: string;
r: string;
s: string;
}>;

export interface AccessListEIP2930RpcTransactionOutput
extends BaseRpcTransactionOutput {
gasPrice: string;
Expand All @@ -75,6 +85,11 @@ export interface EIP1559RpcTransactionOutput extends BaseRpcTransactionOutput {
chainId: string;
}

export interface EOACodeEIP7702TransactionOutput
extends EIP1559RpcTransactionOutput {
authorizationList?: RpcAuthorizationListOutput;
}

export interface RpcReceiptOutput {
blockHash: string;
blockNumber: string;
Expand Down
Loading
Loading