import { BigNumberish , BigNumber , providers , Signer } from "ethers" ; import { CERc20 , CEther , Comp , CompoundGovernorAlpha , CompoundTimelock , CompoundPriceOracleMock , Comptroller , PriceOracleProxy , Unitroller , WhitePaperInterestRateModel , CompoundGovernorBravoDelegate , CompoundGovernorBravoDelegator , } from "../contracts/compound" ; import DeployHelper from "../deploys" ; import { ether , } from "../common" ; import { Address , } from "../types" ; import { ADDRESS_ZERO , ONE_DAY_IN_SECONDS , ZERO , ZERO_BYTES } from "../constants" ; import { getLastBlockTimestamp , increaseTimeAsync } from "../test" ; export class CompoundFixture { private _deployer : DeployHelper ; private _ownerAddress : Address ; private _ownerSigner : Signer ; public unitroller : Unitroller ; public comp : Comp ; public compoundTimelock : CompoundTimelock ; public compoundGovernorAlpha : CompoundGovernorAlpha ; public compoundGovernorBravoDelegate : CompoundGovernorBravoDelegate ; public compoundGovernorBravoDelegator : CompoundGovernorBravoDelegator ; public comptroller : Comptroller ; public interestRateModel : WhitePaperInterestRateModel ; public priceOracle : CompoundPriceOracleMock ; public priceOracleProxy : PriceOracleProxy ; constructor ( provider , ownerAddress ) { this . _ownerAddress = ownerAddress ; this . _ownerSigner = provider . getSigner ( ownerAddress ) ; this . _deployer = new DeployHelper ( this . _ownerSigner ) ; } public async initialize ( ) { this . priceOracle = await this . _deployer . external . deployCompoundPriceOracleMock ( ) ; this . priceOracleProxy = await this . _deployer . external . deployPriceOracleProxy ( ADDRESS_ZERO , this . priceOracle . address , ADDRESS_ZERO , ADDRESS_ZERO , ADDRESS_ZERO , ADDRESS_ZERO , ADDRESS_ZERO ) ; this . unitroller = await this . _deployer . external . deployUnitroller ( ) ; this . comptroller = await this . _deployer . external . deployComptroller ( ) ; await this . unitroller . _setPendingImplementation ( this . comptroller . address ) ; await this . comptroller . _become ( this . unitroller . address , ZERO , [ ] , [ ] ) ; await this . comptroller . _setPriceOracle ( this . priceOracle . address ) ; await this . comptroller . _setMaxAssets ( 10 ) ; await this . comptroller . _setCloseFactor ( ether ( 0.5 ) ) ; await this . comptroller . _setLiquidationIncentive ( ether ( 1.08 ) ) ; this . interestRateModel = await this . _deployer . external . deployWhitePaperInterestRateModel ( ether ( 1 ) , ether ( 1 ) ) ; this . comp = await this . _deployer . external . deployComp ( this . _ownerAddress ) ; await this . comp . transfer ( this . comptroller . address , ether ( 400000 ) ) ; this . compoundTimelock = await this . _deployer . external . deployCompoundTimelock ( this . _ownerAddress , ONE_DAY_IN_SECONDS . mul ( 2 ) ) ; this . compoundGovernorAlpha = await this . _deployer . external . deployCompoundGovernorAlpha ( this . compoundTimelock . address , this . comp . address , this . _ownerAddress ) ; } public async initializeGovernorBravo ( ) { this . compoundGovernorBravoDelegate = await this . _deployer . external . deployCompoundGovernorBravoDelegate ( ) ; this . compoundGovernorBravoDelegator = await this . _deployer . external . deployCompoundGovernorBravoDelegator ( this . compoundTimelock . address , this . comp . address , this . _ownerAddress , this . compoundGovernorBravoDelegate . address , 10000 , 1 , ether ( 100000 ) ) ; const setAdminData = this . compoundTimelock . interface . encodeFunctionData ( "setPendingAdmin" , [ this . compoundGovernorBravoDelegator . address ] ) ; const eta = ( await getLastBlockTimestamp ( ) ) . add ( ONE_DAY_IN_SECONDS . mul ( 2 ) ) . add ( 1 ) ; await this . compoundTimelock . queueTransaction ( this . compoundTimelock . address , 0 , "" , setAdminData , eta ) ; await increaseTimeAsync ( ONE_DAY_IN_SECONDS . mul ( 2 ) . add ( 2 ) ) ; await this . compoundTimelock . executeTransaction ( this . compoundTimelock . address , 0 , "" , setAdminData , eta ) ; await this . comp . delegate ( this . _ownerAddress ) ; await this . compoundGovernorAlpha . connect ( this . _ownerSigner ) . propose ( [ ADDRESS_ZERO ] , [ 0 ] , [ "" ] , [ ZERO_BYTES ] , "dummy prop" ) ; const initiateCallData = this . compoundGovernorBravoDelegate . interface . encodeFunctionData ( "_initiate" , [ this . compoundGovernorAlpha . address ] ) ; await this . compoundGovernorBravoDelegator . fallback ( { data : initiateCallData } ) ; } public async createAndEnableCToken ( underlying , initialExchangeRateMantissa , comptroller = this . unitroller . address , interestRateModel = this . interestRateModel . address , name = "CToken" , symbol = "CT" , decimals = 8 , collateralFactor , currentPrice ) { const newCToken = await this . _deployer . external . deployCeRc20 ( underlying , comptroller , interestRateModel , initialExchangeRateMantissa , name , symbol , decimals ) ; await this . comptroller . _supportMarket ( newCToken . address ) ; await this . priceOracle . setUnderlyingPrice ( newCToken . address , currentPrice ) ; await this . comptroller . _setCollateralFactor ( newCToken . address , collateralFactor ) ; return newCToken ; } public async createAndEnableCEther ( initialExchangeRateMantissa , comptroller = this . unitroller . address , interestRateModel = this . interestRateModel . address , name = "CEther" , symbol = "CETH" , decimals = 8 , collateralFactor , currentPrice ) { const newCToken = await this . _deployer . external . deployCEther ( comptroller , interestRateModel , initialExchangeRateMantissa , name , symbol , decimals ) ; await this . comptroller . _supportMarket ( newCToken . address ) ; await this . priceOracle . setUnderlyingPrice ( newCToken . address , currentPrice ) ; await this . comptroller . _setCollateralFactor ( newCToken . address , collateralFactor ) ; return newCToken ; } }