UNPKG

@hyperlane-xyz/core

Version:

Core solidity contracts for Hyperlane

138 lines (119 loc) 3.73 kB
import assert from 'assert' import { BigNumberish, ethers } from 'ethers' import { Interface } from 'ethers/lib/utils' import { HardhatRuntimeEnvironment } from 'hardhat/types' import { Etherscan } from '../etherscan' export interface DripConfig { reentrant?: boolean interval: BigNumberish dripcheck: string checkparams?: any actions: Array<{ target: string value?: BigNumberish data?: | string | { fn: string args?: any[] } }> } export interface DrippieConfig { [name: string]: DripConfig } export enum Time { SECOND = 1, MINUTE = 60 * Time.SECOND, HOUR = 60 * Time.MINUTE, DAY = 24 * Time.HOUR, WEEK = 7 * Time.DAY, } export const getDrippieConfig = async ( hre: HardhatRuntimeEnvironment ): Promise<Required<DrippieConfig>> => { let config: DrippieConfig try { // eslint-disable-next-line @typescript-eslint/no-var-requires config = require(`../../config/drippie/${hre.network.name}.ts`).default } catch (err) { throw new Error( `error while loading drippie config for network: ${hre.network.name}, ${err}` ) } return parseDrippieConfig(hre, config) } export const encodeDripCheckParams = ( iface: Interface, params: any ): string => { return ethers.utils.defaultAbiCoder.encode( [iface.getEvent('_EventToExposeStructInABI__Params').inputs[0]], [params] ) } export const parseDrippieConfig = async ( hre: HardhatRuntimeEnvironment, config: DrippieConfig ): Promise<Required<DrippieConfig>> => { // Create a clone of the config object. Shallow clone is fine because none of the input options // are expected to be objects or functions etc. const parsed = { ...config } const etherscan = new Etherscan( hre.network.config.verify.etherscan.apiKey, hre.network.config.chainId ) for (const dripConfig of Object.values(parsed)) { for (const action of dripConfig.actions) { assert(ethers.utils.isAddress(action.target), 'target is not an address') if (action.data === undefined) { action.data = '0x' } else if (typeof action.data === 'string') { assert( ethers.utils.isHexString(action.data), 'action is not a hex string' ) } else { const abi = await etherscan.getContractABI(action.target) const iface = new ethers.utils.Interface(abi) action.data = iface.encodeFunctionData( action.data.fn, action.data.args || [] ) } if (action.value === undefined) { action.value = ethers.BigNumber.from(0) } else { action.value = ethers.BigNumber.from(action.value) } } const dripcheck = await hre.deployments.get(dripConfig.dripcheck) dripConfig.dripcheck = dripcheck.address if (dripConfig.checkparams === undefined) { dripConfig.checkparams = '0x' } else { dripConfig.checkparams = encodeDripCheckParams( new ethers.utils.Interface(dripcheck.abi), dripConfig.checkparams ) } dripConfig.interval = ethers.BigNumber.from(dripConfig.interval) dripConfig.reentrant = dripConfig.reentrant || false } return parsed as Required<DrippieConfig> } export const isSameConfig = (a: DripConfig, b: DripConfig): boolean => { return ( a.dripcheck.toLowerCase() === b.dripcheck.toLowerCase() && a.checkparams === b.checkparams && ethers.BigNumber.from(a.interval).eq(b.interval) && a.actions.length === b.actions.length && a.actions.every((ax, i) => { return ( ax.target === b.actions[i].target && ax.data === b.actions[i].data && ethers.BigNumber.from(ax.value).eq(b.actions[i].value) ) }) ) }