hardhat
Version:
Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.
99 lines • 5.06 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLastSafeBlockNumber = exports.makeForkClient = exports.makeForkProvider = void 0;
const chalk_1 = __importDefault(require("chalk"));
const constants_1 = require("../../../constants");
const errors_1 = require("../../../core/errors");
const base_types_1 = require("../../../core/jsonrpc/types/base-types");
const http_1 = require("../../../core/providers/http");
const client_1 = require("../../jsonrpc/client");
const reorgs_protection_1 = require("./reorgs-protection");
// TODO: This is a temporarily measure.
// We must investigate why this timeouts so much. Apparently
// node-fetch doesn't handle timeouts so well. The option was
// removed in its new major version. UPDATE: we aren't even using node-fetch
// anymore, so this really should be revisited.
const FORK_HTTP_TIMEOUT = 35000;
async function makeForkProvider(forkConfig) {
const forkProvider = new http_1.HttpProvider(forkConfig.jsonRpcUrl, constants_1.HARDHAT_NETWORK_NAME, forkConfig.httpHeaders, FORK_HTTP_TIMEOUT);
const networkId = await getNetworkId(forkProvider);
const actualMaxReorg = (0, reorgs_protection_1.getLargestPossibleReorg)(networkId);
const maxReorg = actualMaxReorg ?? reorgs_protection_1.FALLBACK_MAX_REORG;
const latestBlockNumber = await getLatestBlockNumber(forkProvider);
const lastSafeBlockNumber = getLastSafeBlockNumber(latestBlockNumber, maxReorg);
let forkBlockNumber;
if (forkConfig.blockNumber !== undefined) {
if (forkConfig.blockNumber > latestBlockNumber) {
// eslint-disable-next-line @nomicfoundation/hardhat-internal-rules/only-hardhat-error
throw new Error(`Trying to initialize a provider with block ${forkConfig.blockNumber} but the current block is ${latestBlockNumber}`);
}
if (forkConfig.blockNumber > lastSafeBlockNumber) {
const confirmations = latestBlockNumber - BigInt(forkConfig.blockNumber) + 1n;
const requiredConfirmations = maxReorg + 1n;
console.warn(chalk_1.default.yellow(`You are forking from block ${forkConfig.blockNumber}, which has less than ${requiredConfirmations} confirmations, and will affect Hardhat Network's performance.
Please use block number ${lastSafeBlockNumber} or wait for the block to get ${requiredConfirmations - confirmations} more confirmations.`));
}
forkBlockNumber = BigInt(forkConfig.blockNumber);
}
else {
forkBlockNumber = BigInt(lastSafeBlockNumber);
}
return {
forkProvider,
networkId,
forkBlockNumber,
latestBlockNumber,
maxReorg,
};
}
exports.makeForkProvider = makeForkProvider;
async function makeForkClient(forkConfig, forkCachePath) {
const { forkProvider, networkId, forkBlockNumber, latestBlockNumber, maxReorg, } = await makeForkProvider(forkConfig);
const block = await getBlockByNumber(forkProvider, forkBlockNumber);
const forkBlockTimestamp = (0, base_types_1.rpcQuantityToNumber)(block.timestamp) * 1000;
const cacheToDiskEnabled = forkConfig.blockNumber !== undefined && forkCachePath !== undefined;
const forkClient = new client_1.JsonRpcClient(forkProvider, networkId, latestBlockNumber, maxReorg, cacheToDiskEnabled ? forkCachePath : undefined);
const forkBlockHash = block.hash;
(0, errors_1.assertHardhatInvariant)(forkBlockHash !== null, "Forked block should have a hash");
const forkBlockStateRoot = block.stateRoot;
return {
forkClient,
forkBlockNumber,
forkBlockTimestamp,
forkBlockHash,
forkBlockStateRoot,
};
}
exports.makeForkClient = makeForkClient;
async function getBlockByNumber(provider, blockNumber) {
const rpcBlockOutput = (await provider.request({
method: "eth_getBlockByNumber",
params: [(0, base_types_1.numberToRpcQuantity)(blockNumber), false],
}));
return rpcBlockOutput;
}
async function getNetworkId(provider) {
const networkIdString = (await provider.request({
method: "net_version",
}));
return parseInt(networkIdString, 10);
}
async function getLatestBlockNumber(provider) {
const latestBlockString = (await provider.request({
method: "eth_blockNumber",
}));
const latestBlock = BigInt(latestBlockString);
return latestBlock;
}
function getLastSafeBlockNumber(latestBlockNumber, maxReorg) {
// Design choice: if latestBlock - maxReorg results in a negative number then the latestBlock block will be used.
// This decision is based on the assumption that if maxReorg > latestBlock then there is a high probability that the fork is occurring on a devnet.
return latestBlockNumber - maxReorg >= 0
? latestBlockNumber - maxReorg
: latestBlockNumber;
}
exports.getLastSafeBlockNumber = getLastSafeBlockNumber;
//# sourceMappingURL=makeForkClient.js.map
;