Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the Cancun hardfork #4822

Merged
merged 39 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
7a00316
Bump ethereumjs versions
fvictorio Jan 18, 2024
1b2418d
Use equalsBytes and alias bytesToHex to bufferToHex
fvictorio Jan 18, 2024
4fe7e8b
Replace toBuffer with toBytes
fvictorio Jan 18, 2024
37ba634
Fix build and tests
fvictorio Jan 23, 2024
4eb9420
Update pnpm-lock.yaml
fvictorio Feb 5, 2024
0650433
Fix linter
fvictorio Feb 5, 2024
e8cd984
Re-create pnpm-lock.yaml file
fvictorio Feb 5, 2024
929ce31
Remove node: prefix in require
fvictorio Feb 5, 2024
88b51fb
Bump ethereumjs-util dependency in hardhat-ledger
fvictorio Feb 5, 2024
88238c6
add cancun in the supported hardforks: both const variables and readme
ChristopherDedominici Feb 7, 2024
a7937da
add the parentBeaconBlockRoot and the blob fields to the JSON rpc obj
ChristopherDedominici Feb 8, 2024
6a8f51b
Add tests for transient storage opcode
schaable Feb 8, 2024
847f4a0
generate the value for parentBeaconBlockRootGenerator
ChristopherDedominici Feb 9, 2024
e63cade
Add tests for MCOPY
schaable Feb 9, 2024
0642bbc
Add tests for BLOBBASEFEE
schaable Feb 9, 2024
ea02895
move tests in the fork file and add bytecode in beacon root address
ChristopherDedominici Feb 12, 2024
286cfb1
delete unused import
ChristopherDedominici Feb 12, 2024
7b3651c
restore original code
ChristopherDedominici Feb 12, 2024
9205f71
Take genesis block state root from state manager
fvictorio Feb 12, 2024
cde0297
Temporarily skip cancun in default-config.ts test
fvictorio Feb 12, 2024
7f31e47
Use no-ops in originalStoreCache instead of throwing
fvictorio Feb 12, 2024
2f89b30
Fix hexStripZeros helper
fvictorio Feb 12, 2024
4f1508d
Add tests for SELFDESTRUCT
schaable Feb 12, 2024
6239edc
Use right hardfork name when merge is involved
fvictorio Feb 13, 2024
8bb8334
Rename KECCAK256 opcode to SHA3 for backwards compatibility
fvictorio Feb 13, 2024
e4f4b9b
Use correct original contract storage methods
fvictorio Feb 13, 2024
d6778ad
Wrap before/after shanghai tests in a describe
fvictorio Feb 13, 2024
c84329e
Add tests for withdrawals when forking different hardforks
fvictorio Feb 13, 2024
06aaa58
Make cancun work correctly during forking
fvictorio Feb 13, 2024
cf22ac8
Merge pull request #4854 from NomicFoundation/better-different-hardfo…
fvictorio Feb 13, 2024
5ba1b45
Merge pull request #4843 from NomicFoundation/add-parentBeaconBlockRo…
fvictorio Feb 13, 2024
6ff0b20
Create nasty-lies-hug.md
fvictorio Feb 13, 2024
731bdff
Update packages/hardhat-core/test/internal/hardhat-network/provider/n…
schaable Feb 13, 2024
45b8290
Merge pull request #4852 from NomicFoundation/test-new-opcodes
schaable Feb 13, 2024
a3abedc
Reject blob txs with a custom error
fvictorio Feb 13, 2024
8000aad
Remove enableTransientStorage custom logic & throw an error if pre-ca…
schaable Feb 13, 2024
64f299f
Handle enableTransientStorage in config validation and resolution
fvictorio Feb 14, 2024
b33acd7
Merge pull request #4860 from NomicFoundation/update-config-enableTra…
fvictorio Feb 14, 2024
e34908f
Merge pull request #4856 from NomicFoundation/blob-txs
fvictorio Feb 14, 2024
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
5 changes: 5 additions & 0 deletions .changeset/nasty-lies-hug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hardhat": minor
---

Add support for the Cancun hardfork
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 @@ -13,6 +13,7 @@
- grayGlacier
- merge
- shanghai
- cancun

## Config

Expand Down Expand Up @@ -65,7 +66,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"` and `"shanghai"`. Default value: `"shanghai"`
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: `"shanghai"`

#### `throwOnTransactionFailures`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* @author Nomic Foundation
*/
"use strict";
const fs = require("node:fs");
const { isBuiltin } = require("node:module");
const fs = require("fs");
const { isBuiltin } = require("module");
const { relative } = require("eslint-module-utils/resolve");
const parse = require("eslint-module-utils/parse").default;
const visit = require("eslint-module-utils/visit").default;
Expand Down
21 changes: 11 additions & 10 deletions packages/hardhat-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,17 @@
"dependencies": {
"@ethersproject/abi": "^5.1.2",
"@metamask/eth-sig-util": "^4.0.0",
"@nomicfoundation/ethereumjs-block": "5.0.2",
"@nomicfoundation/ethereumjs-blockchain": "7.0.2",
"@nomicfoundation/ethereumjs-common": "4.0.2",
"@nomicfoundation/ethereumjs-evm": "2.0.2",
"@nomicfoundation/ethereumjs-rlp": "5.0.2",
"@nomicfoundation/ethereumjs-statemanager": "2.0.2",
"@nomicfoundation/ethereumjs-trie": "6.0.2",
"@nomicfoundation/ethereumjs-tx": "5.0.2",
"@nomicfoundation/ethereumjs-util": "9.0.2",
"@nomicfoundation/ethereumjs-vm": "7.0.2",
"@nomicfoundation/ethereumjs-block": "5.0.4",
"@nomicfoundation/ethereumjs-blockchain": "7.0.4",
"@nomicfoundation/ethereumjs-common": "4.0.4",
"@nomicfoundation/ethereumjs-evm": "2.0.4",
"@nomicfoundation/ethereumjs-rlp": "5.0.4",
"@nomicfoundation/ethereumjs-statemanager": "2.0.4",
"@nomicfoundation/ethereumjs-trie": "6.0.4",
"@nomicfoundation/ethereumjs-tx": "5.0.4",
"@nomicfoundation/ethereumjs-util": "9.0.4",
"@nomicfoundation/ethereumjs-verkle": "0.0.2",
"@nomicfoundation/ethereumjs-vm": "7.0.4",
"@nomicfoundation/solidity-analyzer": "^0.1.0",
"@sentry/node": "^5.18.1",
"@types/bn.js": "^5.1.0",
Expand Down
12 changes: 8 additions & 4 deletions packages/hardhat-core/src/builtin-tasks/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,12 @@ function logHardhatNetworkAccounts(networkConfig: HardhatNetworkConfig) {
!Array.isArray(networkConfig.accounts) &&
networkConfig.accounts.mnemonic === HARDHAT_NETWORK_MNEMONIC;

const { bufferToHex, privateToAddress, toBuffer, toChecksumAddress } =
require("@nomicfoundation/ethereumjs-util") as typeof EthereumjsUtilT;
const {
bytesToHex: bufferToHex,
privateToAddress,
toBytes,
toChecksumAddress,
} = require("@nomicfoundation/ethereumjs-util") as typeof EthereumjsUtilT;

console.log("Accounts");
console.log("========");
Expand All @@ -69,15 +73,15 @@ function logHardhatNetworkAccounts(networkConfig: HardhatNetworkConfig) {

for (const [index, account] of accounts.entries()) {
const address = toChecksumAddress(
bufferToHex(privateToAddress(toBuffer(account.privateKey)))
bufferToHex(privateToAddress(toBytes(account.privateKey)))
);

const balance = (BigInt(account.balance) / 10n ** 18n).toString(10);

let entry = `Account #${index}: ${address} (${balance} ETH)`;

if (isDefaultConfig) {
const privateKey = bufferToHex(toBuffer(account.privateKey));
const privateKey = bufferToHex(toBytes(account.privateKey));
entry += `
Private Key: ${privateKey}`;
}
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 @@ -22,6 +22,7 @@ export const HARDHAT_NETWORK_SUPPORTED_HARDFORKS = [
"grayGlacier",
"merge",
"shanghai",
"cancun",
];

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,6 +238,19 @@ 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 @@ -498,6 +498,25 @@ export function getValidationErrors(config: any): string[] {
}
});
}

if (hardhatNetwork.hardfork !== undefined) {
if (
!hardforkGte(hardhatNetwork.hardfork, HardforkName.CANCUN) &&
hardhatNetwork.enableTransientStorage === true
) {
errors.push(
`'enableTransientStorage' cannot be enabled if the hardfork is explicitly set to a pre-cancun value. If you want to use transient storage, use 'cancun' as the hardfork.`
);
}
if (
hardforkGte(hardhatNetwork.hardfork, HardforkName.CANCUN) &&
hardhatNetwork.enableTransientStorage === false
) {
errors.push(
`'enableTransientStorage' cannot be disabled if the hardfork is explicitly set to cancun or later. If you want to disable transient storage, use a hardfork before 'cancun'.`
);
}
}
}

for (const [networkName, netConfig] of Object.entries<any>(
Expand Down
11 changes: 11 additions & 0 deletions packages/hardhat-core/src/internal/core/config/default-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,17 @@ export const defaultHardhatNetworkParams: Omit<
]),
},
],
[
11155111, // sepolia
{
hardforkHistory: new Map([
[HardforkName.GRAY_GLACIER, 0],
[HardforkName.MERGE, 1_450_409],
[HardforkName.SHANGHAI, 2_990_908],
[HardforkName.CANCUN, 5_187_023],
]),
},
],
]),
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
bufferToHex,
bytesToHex as bufferToHex,
isValidAddress,
toBuffer,
toBytes,
} from "@nomicfoundation/ethereumjs-util";
import * as t from "io-ts";

Expand All @@ -22,14 +22,16 @@ export const rpcQuantity = new t.Type<bigint>(
export const rpcData = new t.Type<Buffer>(
"DATA",
Buffer.isBuffer,
(u, c) => (isRpcDataString(u) ? t.success(toBuffer(u)) : t.failure(u, c)),
(u, c) =>
isRpcDataString(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,
(u, c) => (isRpcHashString(u) ? t.success(toBuffer(u)) : t.failure(u, c)),
(u, c) =>
isRpcHashString(u) ? t.success(Buffer.from(toBytes(u))) : t.failure(u, c),
t.identity
);

Expand Down Expand Up @@ -96,7 +98,10 @@ function validateStorageSlot(u: unknown, c: t.Context): t.Validation<bigint> {
export const rpcAddress = new t.Type<Buffer>(
"ADDRESS",
(v): v is Buffer => Buffer.isBuffer(v) && v.length === ADDRESS_LENGTH_BYTES,
(u, c) => (isRpcAddressString(u) ? t.success(toBuffer(u)) : t.failure(u, c)),
(u, c) =>
isRpcAddressString(u)
? t.success(Buffer.from(toBytes(u)))
: t.failure(u, c),
t.identity
);

Expand Down Expand Up @@ -173,7 +178,7 @@ export function rpcDataToBigInt(data: string): bigint {
}

export function bufferToRpcData(
buffer: Buffer,
buffer: Uint8Array,
padToBytes: number = 0
): string {
let s = bufferToHex(buffer);
Expand All @@ -191,7 +196,7 @@ export function rpcDataToBuffer(data: string): Buffer {
});
}

return toBuffer(data);
return Buffer.from(toBytes(data));
}

// Type guards
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { rpcAccessList } from "../access-list";
import {
rpcAddress,
rpcData,
rpcHash,
rpcQuantity,
rpcStorageSlot,
rpcStorageSlotHexString,
Expand All @@ -23,6 +24,8 @@ export const rpcCallRequest = t.type(
accessList: optionalOrNullable(rpcAccessList),
maxFeePerGas: optionalOrNullable(rpcQuantity),
maxPriorityFeePerGas: optionalOrNullable(rpcQuantity),
blobs: optionalOrNullable(t.array(rpcData)),
blobVersionedHashes: optionalOrNullable(t.array(rpcHash)),
},
"RpcCallRequest"
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as t from "io-ts";

import { optionalOrNullable } from "../../../../util/io-ts";
import { rpcAccessList } from "../access-list";
import { rpcAddress, rpcData, rpcQuantity } from "../base-types";
import { rpcAddress, rpcData, rpcHash, rpcQuantity } from "../base-types";

// Type used by eth_sendTransaction
export const rpcTransactionRequest = t.type(
Expand All @@ -18,6 +18,8 @@ export const rpcTransactionRequest = t.type(
chainId: optionalOrNullable(rpcQuantity),
maxFeePerGas: optionalOrNullable(rpcQuantity),
maxPriorityFeePerGas: optionalOrNullable(rpcQuantity),
blobs: optionalOrNullable(t.array(rpcData)),
blobVersionedHashes: optionalOrNullable(t.array(rpcHash)),
},
"RpcTransactionRequest"
);
Expand All @@ -38,6 +40,8 @@ export interface RpcTransactionRequestInput {
}>;
maxFeePerGas?: string;
maxPriorityFeePerGas?: string;
blobs?: string[];
blobVersionedHashes?: string[];
}

export type RpcTransactionRequest = t.TypeOf<typeof rpcTransactionRequest>;
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ const baseBlockResponse = {
baseFeePerGas: optional(rpcQuantity),
withdrawals: optional(t.array(rpcWithdrawalItem)),
withdrawalsRoot: optional(rpcHash),
parentBeaconBlockRoot: optional(rpcHash),
blobGasUsed: optional(rpcQuantity),
excessBlobGas: optional(rpcQuantity),
};

export type RpcBlock = t.TypeOf<typeof rpcBlock>;
Expand Down
37 changes: 24 additions & 13 deletions packages/hardhat-core/src/internal/core/providers/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,13 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {
}

public async request(args: RequestArguments): Promise<unknown> {
const { ecsign, hashPersonalMessage, toRpcSig, toBuffer, bufferToHex } =
await import("@nomicfoundation/ethereumjs-util");
const {
ecsign,
hashPersonalMessage,
toRpcSig,
toBytes,
bytesToHex: bufferToHex,
} = await import("@nomicfoundation/ethereumjs-util");

if (
args.method === "eth_accounts" ||
Expand All @@ -65,7 +70,7 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {
}

const privateKey = this._getPrivateKeyForAddress(address);
const messageHash = hashPersonalMessage(toBuffer(data));
const messageHash = hashPersonalMessage(toBytes(data));
const signature = ecsign(messageHash, privateKey);
return toRpcSig(signature.v, signature.r, signature.s);
}
Expand All @@ -84,7 +89,7 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {
}

const privateKey = this._getPrivateKeyForAddress(address);
const messageHash = hashPersonalMessage(toBuffer(data));
const messageHash = hashPersonalMessage(toBytes(data));
const signature = ecsign(messageHash, privateKey);
return toRpcSig(signature.v, signature.r, signature.s);
}
Expand Down Expand Up @@ -189,13 +194,13 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {

private _initializePrivateKeys(localAccountsHexPrivateKeys: string[]) {
const {
bufferToHex,
toBuffer,
bytesToHex: bufferToHex,
toBytes,
privateToAddress,
} = require("@nomicfoundation/ethereumjs-util");

const privateKeys: Buffer[] = localAccountsHexPrivateKeys.map((h) =>
toBuffer(h)
toBytes(h)
);

for (const pk of privateKeys) {
Expand All @@ -205,7 +210,9 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {
}

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

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

const response = (await this._wrappedProvider.request({
method: "eth_getTransactionCount",
Expand All @@ -239,8 +248,8 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {
transactionRequest: RpcTransactionRequest,
chainId: number,
privateKey: Buffer
): Promise<Buffer> {
const { AccessListEIP2930Transaction, Transaction } = await import(
): Promise<Uint8Array> {
const { AccessListEIP2930Transaction, LegacyTransaction } = await import(
"@nomicfoundation/ethereumjs-tx"
);

Expand Down Expand Up @@ -282,7 +291,7 @@ export class LocalAccountsProvider extends ProviderWrapperWithChainId {
{ common }
);
} else {
transaction = Transaction.fromTxData(txData, { common });
transaction = LegacyTransaction.fromTxData(txData, { common });
}

const signedTransaction = transaction.sign(privateKey);
Expand Down Expand Up @@ -311,7 +320,9 @@ export class HDWalletProvider extends LocalAccountsProvider {
passphrase
);

const { bufferToHex } = require("@nomicfoundation/ethereumjs-util");
const {
bytesToHex: bufferToHex,
} = require("@nomicfoundation/ethereumjs-util");
const privateKeysAsHex = privateKeys.map((pk) => bufferToHex(pk));
super(provider, privateKeysAsHex);
}
Expand Down
Loading
Loading