hardhat
Version:
Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.
199 lines • 8.47 kB
JavaScript
import { GasEstimationMode, GasReportExecutionStatus, l1HardforkToString, MineOrdering, opHardforkToString, } from "@nomicfoundation/edr";
import { min } from "@nomicfoundation/hardhat-utils/bigint";
import { GENERIC_CHAIN_TYPE, L1_CHAIN_TYPE, OPTIMISM_CHAIN_TYPE, } from "../../../../constants.js";
import { FixedValueConfigurationVariable } from "../../../../core/configuration-variables.js";
import { derivePrivateKeys } from "../../accounts/derive-private-keys.js";
import { getPrivateKey } from "../../accounts/get-private-key.js";
import { DEFAULT_EDR_NETWORK_BALANCE, EDR_NETWORK_DEFAULT_PRIVATE_KEYS, EIP_7825_TRANSACTION_GAS_CAP, EIP_8037_MAX_TRANSACTION_GAS_LIMIT, isDefaultEdrNetworkHDAccountsConfig, } from "../edr-constants.js";
import { hardforkGte, L1HardforkName } from "../types/hardfork.js";
import { getHardforkName, getL1HardforkName, getOpHardforkName, } from "./hardfork.js";
/**
* Returns Hardhat's name for an EDR hardfork.
*/
export function edrL1HardforkToHardhatL1HardforkName(hardfork) {
return getL1HardforkName(l1HardforkToString(hardfork));
}
/**
* Returns Hardhat's name for an EDR OP hardfork. See
* {@link edrL1HardforkToHardhatL1HardforkName}.
*/
export function edrOpHardforkToHardhatOpHardforkName(hardfork) {
return getOpHardforkName(opHardforkToString(hardfork));
}
export function hardhatMiningIntervalToEdrMiningInterval(config) {
if (typeof config === "number") {
// Is interval mining disabled?
if (config === 0) {
return undefined;
}
else {
return BigInt(config);
}
}
else {
return {
min: BigInt(Math.max(1, config[0])),
max: BigInt(Math.max(1, config[1])),
};
}
}
export function hardhatMempoolOrderToEdrMineOrdering(mempoolOrder) {
switch (mempoolOrder) {
case "fifo":
return MineOrdering.Fifo;
case "priority":
return MineOrdering.Priority;
}
}
export function hardhatGasEstimationModeToEdrGasEstimationMode(gasEstimationMode) {
switch (gasEstimationMode) {
case "topLevelSuccess":
return GasEstimationMode.TopLevelSuccess;
case "noInternalOutOfGas":
return GasEstimationMode.NoInternalOutOfGas;
}
}
export async function hardhatAccountsToEdrOwnedAccounts(accounts) {
const normalizedAccounts = await normalizeEdrNetworkAccountsConfig(accounts);
const accountPromises = normalizedAccounts.map(async (account) => ({
secretKey: await getPrivateKey(account.privateKey),
balance: account.balance,
}));
return await Promise.all(accountPromises);
}
export async function normalizeEdrNetworkAccountsConfig(accounts) {
if (Array.isArray(accounts)) {
return accounts;
}
const isDefaultConfig = await isDefaultEdrNetworkHDAccountsConfig(accounts);
const derivedPrivateKeys = isDefaultConfig
? EDR_NETWORK_DEFAULT_PRIVATE_KEYS
: await derivePrivateKeys(await accounts.mnemonic.get(), accounts.path, accounts.initialIndex, accounts.count, await accounts.passphrase.get());
return derivedPrivateKeys.map((privateKey) => ({
privateKey: new FixedValueConfigurationVariable(privateKey),
balance: accounts.accountsBalance ?? DEFAULT_EDR_NETWORK_BALANCE,
}));
}
export function hardhatChainDescriptorsToEdrChainOverrides(chainDescriptors, chainType) {
return (Array.from(chainDescriptors)
// Skip chain descriptors that don't match the expected chain type
.filter(([_, descriptor]) => {
if (chainType === GENERIC_CHAIN_TYPE) {
// When "generic" is requested, include both "generic" and "l1" chains
return (descriptor.chainType === GENERIC_CHAIN_TYPE ||
descriptor.chainType === L1_CHAIN_TYPE);
}
return descriptor.chainType === chainType;
})
.map(([chainId, descriptor]) => {
const chainOverride = {
chainId,
name: descriptor.name,
};
if (descriptor.hardforkHistory !== undefined) {
chainOverride.hardforkActivationOverrides = Array.from(descriptor.hardforkHistory).map(([hardfork, { blockNumber, timestamp }]) => ({
condition: blockNumber !== undefined
? { blockNumber: BigInt(blockNumber) }
: { timestamp: BigInt(timestamp) },
hardfork: getHardforkName(hardfork, descriptor.chainType),
}));
}
return chainOverride;
}));
}
export async function hardhatForkingConfigToEdrForkConfig(forkingConfig, chainDescriptors, chainType) {
let fork;
if (forkingConfig !== undefined && forkingConfig.enabled === true) {
const httpHeaders = forkingConfig.httpHeaders !== undefined
? Object.entries(forkingConfig.httpHeaders).map(([name, value]) => ({
name,
value,
}))
: undefined;
fork = {
blockNumber: forkingConfig.blockNumber,
cacheDir: forkingConfig.cacheDir,
chainOverrides: hardhatChainDescriptorsToEdrChainOverrides(chainDescriptors, chainType),
httpHeaders,
url: await forkingConfig.url.getUrl(),
};
}
return fork;
}
/**
* Resolves the default transaction gas limit used by RPC call and
* transaction requests that omit a `gas` field. This includes
* `eth_estimateGas`: when the request doesn't specify `gas`, EDR uses this
* value as the upper bound of the estimation, so it should be the most gas a
* transaction can use.
*
* From L1's Amsterdam hardfork onwards, EIP-8037 limits `transactionGasCap`
* to execution gas, and a transaction can use up to the minimum of the block
* gas limit or 2^32 - 1, no matter what `transactionGasCap` is.
*
* Before Amsterdam, when `transactionGasCap` is a bigint, that value wins.
* When it is `false`, the per-transaction cap is disabled and the block gas
* limit is used. When it is undefined, the hardfork-specific default applies:
* from L1's Osaka hardfork onwards, the EIP-7825 transaction gas cap of
* 16,777,216; otherwise the block gas limit.
*/
export function resolveDefaultTransactionGasLimit(params) {
const { chainType, hardfork, blockGasLimit, transactionGasCap } = params;
if (chainType !== OPTIMISM_CHAIN_TYPE &&
hardforkGte(hardfork, L1HardforkName.AMSTERDAM, chainType)) {
return min(blockGasLimit, EIP_8037_MAX_TRANSACTION_GAS_LIMIT);
}
if (typeof transactionGasCap === "bigint") {
return transactionGasCap;
}
if (transactionGasCap === false) {
return blockGasLimit;
}
// TODO: OP UPGRADE 19 - update OP to also set a default transaction gas once enabled
if (chainType === OPTIMISM_CHAIN_TYPE) {
return blockGasLimit;
}
if (hardforkGte(hardfork, L1HardforkName.OSAKA, chainType)) {
return EIP_7825_TRANSACTION_GAS_CAP;
}
return blockGasLimit;
}
/**
* Converts EDR's nested GasReport structure into a flat array of gas entries.
* Filters out reverted transactions.
*/
export function edrGasReportToHardhatGasMeasurements(gasReport, excludedContractFqns = []) {
const gasMeasurements = [];
for (const [contractFqn, data] of Object.entries(gasReport.contracts)) {
if (excludedContractFqns.includes(contractFqn)) {
continue;
}
// Process deployments
for (const deployment of data.deployments) {
if (deployment.status === GasReportExecutionStatus.Success) {
gasMeasurements.push({
contractFqn,
type: "deployment",
gas: Number(deployment.gas),
runtimeSize: Number(deployment.runtimeSize),
});
}
}
// Process function calls
for (const [functionSig, calls] of Object.entries(data.functions)) {
for (const call of calls) {
if (call.status === GasReportExecutionStatus.Success) {
gasMeasurements.push({
contractFqn,
type: "function",
functionSig,
gas: Number(call.gas),
proxyChain: call.proxyChain,
});
}
}
}
}
return gasMeasurements;
}
//# sourceMappingURL=convert-to-edr.js.map