hardhat
Version:
Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.
124 lines (110 loc) • 4.11 kB
text/typescript
import { HardforkHistoryConfig } from "../../types/config";
import { HARDHAT_NETWORK_SUPPORTED_HARDFORKS } from "../constants";
import { assertHardhatInvariant } from "../core/errors";
import { InternalError } from "../core/providers/errors";
/* eslint-disable @nomicfoundation/hardhat-internal-rules/only-hardhat-error */
export enum HardforkName {
FRONTIER = "chainstart",
HOMESTEAD = "homestead",
DAO = "dao",
TANGERINE_WHISTLE = "tangerineWhistle",
SPURIOUS_DRAGON = "spuriousDragon",
BYZANTIUM = "byzantium",
CONSTANTINOPLE = "constantinople",
PETERSBURG = "petersburg",
ISTANBUL = "istanbul",
MUIR_GLACIER = "muirGlacier",
BERLIN = "berlin",
LONDON = "london",
ARROW_GLACIER = "arrowGlacier",
GRAY_GLACIER = "grayGlacier",
MERGE = "merge",
SHANGHAI = "shanghai",
CANCUN = "cancun",
}
const HARDFORKS_ORDER: HardforkName[] = [
HardforkName.FRONTIER,
HardforkName.HOMESTEAD,
HardforkName.DAO,
HardforkName.TANGERINE_WHISTLE,
HardforkName.SPURIOUS_DRAGON,
HardforkName.BYZANTIUM,
HardforkName.CONSTANTINOPLE,
HardforkName.PETERSBURG,
HardforkName.ISTANBUL,
HardforkName.MUIR_GLACIER,
HardforkName.BERLIN,
HardforkName.LONDON,
HardforkName.ARROW_GLACIER,
HardforkName.GRAY_GLACIER,
HardforkName.MERGE,
HardforkName.SHANGHAI,
HardforkName.CANCUN,
];
export function getHardforkName(name: string): HardforkName {
const hardforkName =
Object.values(HardforkName)[
Object.values<string>(HardforkName).indexOf(name)
];
assertHardhatInvariant(
hardforkName !== undefined,
`Invalid harfork name ${name}`
);
return hardforkName;
}
/**
* Check if `hardforkA` is greater than or equal to `hardforkB`,
* that is, if it includes all its changes.
*/
export function hardforkGte(
hardforkA: HardforkName,
hardforkB: HardforkName
): boolean {
// This function should not load any ethereumjs library, as it's used during
// the Hardhat initialization, and that would make it too slow.
const indexA = HARDFORKS_ORDER.lastIndexOf(hardforkA);
const indexB = HARDFORKS_ORDER.lastIndexOf(hardforkB);
return indexA >= indexB;
}
export function selectHardfork(
forkBlockNumber: bigint | undefined,
currentHardfork: string,
hardforkActivations: HardforkHistoryConfig | undefined,
blockNumber: bigint
): string {
if (forkBlockNumber === undefined || blockNumber > forkBlockNumber) {
return currentHardfork;
}
if (hardforkActivations === undefined || hardforkActivations.size === 0) {
throw new InternalError(
`No known hardfork for execution on historical block ${blockNumber.toString()} (relative to fork block number ${forkBlockNumber}). The node was not configured with a hardfork activation history. See http://hardhat.org/custom-hardfork-history`
);
}
/** search this._hardforkActivations for the highest block number that
* isn't higher than blockNumber, and then return that found block number's
* associated hardfork name. */
const hardforkHistory: Array<[name: string, block: number]> = Array.from(
hardforkActivations.entries()
);
const [hardfork, activationBlock] = hardforkHistory.reduce(
([highestHardfork, highestBlock], [thisHardfork, thisBlock]) =>
thisBlock > highestBlock && thisBlock <= blockNumber
? [thisHardfork, thisBlock]
: [highestHardfork, highestBlock]
);
if (hardfork === undefined || blockNumber < activationBlock) {
throw new InternalError(
`Could not find a hardfork to run for block ${blockNumber.toString()}, after having looked for one in the hardfork activation history, which was: ${JSON.stringify(
hardforkHistory
)}. For more information, see https://hardhat.org/hardhat-network/reference/#config`
);
}
if (!HARDHAT_NETWORK_SUPPORTED_HARDFORKS.includes(hardfork)) {
throw new InternalError(
`Tried to run a call or transaction in the context of a block whose hardfork is "${hardfork}", but Hardhat Network only supports the following hardforks: ${HARDHAT_NETWORK_SUPPORTED_HARDFORKS.join(
", "
)}`
);
}
return hardfork;
}