Skip to content
This repository was archived by the owner on Dec 10, 2025. It is now read-only.
Open
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
133 changes: 105 additions & 28 deletions helpers/misc-utils.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,69 @@
import BigNumber from "bignumber.js";
import BN = require("bn.js");
import { BigNumber as BigNumberJS } from "bignumber.js";
import { BigNumber, Wallet, ContractTransaction } from "ethers";
import low from "lowdb";
import FileSync from "lowdb/adapters/FileSync";
import { HardhatRuntimeEnvironment } from "hardhat/types"; // Updated dependency name
import { WAD } from "./constants";
import { Wallet, ContractTransaction } from "ethers";
import { BuidlerRuntimeEnvironment } from "@nomiclabs/buidler/types";
import { iParamsPerNetwork, eEthereumNetwork } from "./types";

export const toWad = (value: string | number) =>
new BigNumber(value).times(WAD).toFixed();
// NOTE: Hardhat/Ethers.js provides its own BigNumber implementation.
// We use BigNumberJS (from bignumber.js) here primarily for arithmetic precision
// before converting back to Ethers BigNumber or string for contract interaction.

export const bnToBigNumber = (amount: BN): BigNumber =>
new BigNumber(<any>amount);
export const stringToBigNumber = (amount: string): BigNumber =>
new BigNumber(amount);
// --- Configuration and Environment Setup ---

// Default path for contract addresses persistence
export const getDb = () => low(new FileSync("./deployed-contracts.json"));

export let BRE: BuidlerRuntimeEnvironment = {} as BuidlerRuntimeEnvironment;
export const setBRE = (_BRE: BuidlerRuntimeEnvironment) => {
BRE = _BRE;
// Using a type alias for the global environment, which should ideally be passed around,
// not stored globally (see comment below).
export type HRE = HardhatRuntimeEnvironment;

// WARNING: Storing HRE globally is risky. It's better to pass it as an argument
// to functions that need it (e.g., evmSnapshot).
// If absolutely necessary, keep the setter/getter pattern:
export let hre: HRE = {} as HRE;
export const setHRE = (_hre: HRE) => {
hre = _hre;
};

export const getParamPerNetwork = <T>(
// --- Conversion and Utility Functions ---

/**
* Converts a standard decimal value (e.g., '1.0' or 1) into a WAD (1e18) string format.
* This is crucial for interacting with Aave/Compound-like protocols.
* @param value The value to convert (e.g., 1.23)
* @returns The WAD representation as a string (e.g., '1230000000000000000')
*/
export const toWad = (value: string | number): string =>
new BigNumberJS(value).times(WAD).toFixed(0); // Ensure no decimals in the final integer string

/**
* Converts an Ethers BigNumber to BigNumberJS for high-precision arithmetic.
* @param amount The Ethers BigNumber object.
* @returns The BigNumberJS object.
*/
export const ethersBnToBigNumberJS = (amount: BigNumber): BigNumberJS =>
new BigNumberJS(amount.toString());

/**
* Converts a string amount to BigNumberJS for high-precision arithmetic.
* @param amount The amount as a string.
* @returns The BigNumberJS object.
*/
export const stringToBigNumberJS = (amount: string): BigNumberJS =>
new BigNumberJS(amount);

/**
* Retrieves the correct parameter value based on the current Ethereum network environment.
* @param params Object containing network-specific parameters.
* @param network The current network enum.
* @returns The parameter value for the specified network.
*/
export const getParamByNetwork = <T>(
{ kovan, ropsten, main, buidlerevm, coverage }: iParamsPerNetwork<T>,
network: eEthereumNetwork
) => {
): T => {
switch (network) {
case eEthereumNetwork.coverage:
return coverage;
Expand All @@ -38,31 +76,70 @@ export const getParamPerNetwork = <T>(
case eEthereumNetwork.main:
return main;
default:
// Defaulting to 'main' is acceptable if the configuration ensures 'main' always exists.
return main;
}
};

export const sleep = (milliseconds: number) => {
/**
* Pauses execution for a specified number of milliseconds.
* @param milliseconds Time to sleep.
*/
export const sleep = (milliseconds: number): Promise<void> => {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
};

export const createRandomAddress = () => Wallet.createRandom().address;
/**
* Creates a new randomly generated Ethereum wallet and returns its address.
* @returns A randomly generated Ethereum address.
*/
export const createRandomAddress = (): string => Wallet.createRandom().address;

/**
* Waits for a transaction to be mined and returns the receipt.
* @param tx The contract transaction promise.
* @returns The transaction receipt.
*/
export const waitForTx = async (tx: ContractTransaction) => await tx.wait();

export const evmSnapshot = async () =>
await BRE.ethereum.send("evm_snapshot", []);

export const evmRevert = async (id: string) =>
BRE.ethereum.send("evm_revert", [id]);
// --- EVM Manipulation Functions (Require HRE/hre to be set) ---

/**
* Creates a snapshot of the current EVM state.
* @returns The snapshot ID as a string.
*/
export const evmSnapshot = async (): Promise<string> =>
await hre.ethers.provider.send("evm_snapshot", []);

/**
* Reverts the EVM to a previously saved snapshot.
* @param id The ID of the snapshot to revert to.
*/
export const evmRevert = async (id: string): Promise<void> =>
await hre.ethers.provider.send("evm_revert", [id]);

export const timeLatest = async () => {
const block = await BRE.ethers.provider.getBlock("latest");
return new BigNumber(block.timestamp);
/**
* Gets the timestamp of the latest mined block.
* @returns The timestamp as a BigNumberJS object.
*/
export const timeLatest = async (): Promise<BigNumberJS> => {
const block = await hre.ethers.provider.getBlock("latest");
// Use BigNumberJS for potential large timestamps
return new BigNumberJS(block.timestamp);
};

export const advanceBlock = async (timestamp: number) =>
await BRE.ethers.provider.send("evm_mine", [timestamp]);
/**
* Mines a new block with a specific timestamp.
* @param timestamp The Unix timestamp for the new block.
*/
export const advanceBlock = async (timestamp: number): Promise<void> =>
await hre.ethers.provider.send("evm_mine", [timestamp]);

export const increaseTime = async (secondsToIncrease: number) =>
await BRE.ethers.provider.send("evm_increaseTime", [secondsToIncrease]);
/**
* Increases the EVM's block time by a specified number of seconds.
* Note: A subsequent block mine is needed to activate the time increase.
* @param secondsToIncrease The number of seconds to advance the time by.
*/
export const increaseTime = async (secondsToIncrease: number): Promise<void> =>
await hre.ethers.provider.send("evm_increaseTime", [secondsToIncrease]);