drippie.ts 3.65 KB
Newer Older
1 2 3 4 5 6 7 8 9
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 {
10
  reentrant?: boolean
11 12 13 14 15 16 17 18 19 20
  interval: BigNumberish
  dripcheck: string
  checkparams?: any
  actions: Array<{
    target: string
    value?: BigNumberish
    data?:
      | string
      | {
          fn: string
21
          args?: any[]
22 23 24 25 26 27 28 29
        }
  }>
}

export interface DrippieConfig {
  [name: string]: DripConfig
}

30 31 32 33 34 35 36 37
export enum Time {
  SECOND = 1,
  MINUTE = 60 * Time.SECOND,
  HOUR = 60 * Time.MINUTE,
  DAY = 24 * Time.HOUR,
  WEEK = 7 * Time.DAY,
}

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
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)
91 92 93 94
        action.data = iface.encodeFunctionData(
          action.data.fn,
          action.data.args || []
        )
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
      }

      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)
117
    dripConfig.reentrant = dripConfig.reentrant || false
118 119 120 121
  }

  return parsed as Required<DrippieConfig>
}
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137

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)
      )
    })
  )
}