test-report

Test coverage

To check test coverage you can run:

yarn coverage

You can see the coverage status at mainnet deployment here.

Impacted file tree graph

There’s also a pull request to increase the coverage, but it hasn’t been merged yet because it modifies some smart contracts (mostly removing unnecessary checks).

Test output

The following is the output of a complete test run, made on commit a1824dd8, from April 16th, 2021.

yarn run v1.22.11
$ hardhat test


  Contract: Access Control: Mosaic functions with the caller restricted to Mosaic contract(s)
    BorrowerOperations
      ✓ moveETHGainToTrove(): reverts when called by an account that is not StabilityPool
    TroveManager
      ✓ applyPendingRewards(): reverts when called by an account that is not BorrowerOperations
      ✓ updateRewardSnapshots(): reverts when called by an account that is not BorrowerOperations
      ✓ removeStake(): reverts when called by an account that is not BorrowerOperations
      ✓ updateStakeAndTotalStakes(): reverts when called by an account that is not BorrowerOperations
      ✓ closeTrove(): reverts when called by an account that is not BorrowerOperations
      ✓ addTroveOwnerToArray(): reverts when called by an account that is not BorrowerOperations
      ✓ setTroveStatus(): reverts when called by an account that is not BorrowerOperations
      ✓ increaseTroveColl(): reverts when called by an account that is not BorrowerOperations
      ✓ decreaseTroveColl(): reverts when called by an account that is not BorrowerOperations
      ✓ increaseTroveDebt(): reverts when called by an account that is not BorrowerOperations
      ✓ decreaseTroveDebt(): reverts when called by an account that is not BorrowerOperations
    ActivePool
      ✓ sendETH(): reverts when called by an account that is not BO nor TroveM nor SP
      ✓ increaseMoUSDDebt(): reverts when called by an account that is not BO nor TroveM
      ✓ decreaseMoUSDDebt(): reverts when called by an account that is not BO nor TroveM nor SP
      ✓ fallback(): reverts when called by an account that is not Borrower Operations nor Default Pool
    DefaultPool
      ✓ sendETHToActivePool(): reverts when called by an account that is not TroveManager
      ✓ increaseMoUSDDebt(): reverts when called by an account that is not TroveManager
      ✓ decreaseMoUSD(): reverts when called by an account that is not TroveManager
      ✓ fallback(): reverts when called by an account that is not the Active Pool
    StabilityPool
      ✓ offset(): reverts when called by an account that is not TroveManager
      ✓ fallback(): reverts when called by an account that is not the Active Pool
    MoUSDToken
      ✓ mint(): reverts when called by an account that is not BorrowerOperations
      ✓ burn(): reverts when called by an account that is not BO nor TroveM nor SP
      ✓ sendToPool(): reverts when called by an account that is not StabilityPool
      ✓ returnFromPool(): reverts when called by an account that is not TroveManager nor StabilityPool
    SortedTroves
      ✓ insert(): reverts when called by an account that is not BorrowerOps or TroveM
      ✓ remove(): reverts when called by an account that is not TroveManager
      ✓ reinsert(): reverts when called by an account that is neither BorrowerOps nor TroveManager
    LockupContract
      ✓ withdrawMSIC(): reverts when caller is not beneficiary (68ms)
    MSICStaking
      ✓ increaseF_MoUSD(): reverts when caller is not TroveManager
    MSICToken
      ✓ sendToMSICStaking(): reverts when caller is not the MSICSstaking (49ms)
    CommunityIssuance
      ✓ sendMSIC(): reverts when caller is not the StabilityPool
      ✓ issueMSIC(): reverts when caller is not the StabilityPool

  Contract: BorrowerOperations
    Without proxy
      ✓ addColl(): reverts when top-up would leave trove with ICR < MCR (278ms)
      ✓ addColl(): Increases the activePool REEF and raw ether balance by correct amount (203ms)
      ✓ addColl(), active Trove: adds the correct collateral amount to the Trove (194ms)
      ✓ addColl(), active Trove: Trove is in sortedList before and after (213ms)
      ✓ addColl(), active Trove: updates the stake and updates the total stakes (225ms)
      ✓ addColl(), active Trove: applies pending rewards and updates user's L_ETH, L_MoUSDDebt snapshots (736ms)
      ✓ addColl(), reverts if trove is non-existent or closed (831ms)
      ✓ addColl(): can add collateral in Recovery Mode (252ms)
      ✓ withdrawColl(): reverts when withdrawal would leave trove with ICR < MCR (349ms)
      ✓ withdrawColl(): reverts when calling address does not have active trove (328ms)
      ✓ withdrawColl(): reverts when system is in Recovery Mode (420ms)
      ✓ withdrawColl(): reverts when requested REEF withdrawal is > the trove's collateral (508ms)
      ✓ withdrawColl(): reverts when withdrawal would bring the user's ICR < MCR (313ms)
      ✓ withdrawColl(): reverts if system is in Recovery Mode (323ms)
      ✓ withdrawColl(): doesn’t allow a user to completely withdraw all collateral from their Trove (due to gas compensation) (352ms)
      ✓ withdrawColl(): leaves the Trove active when the user withdraws less than all the collateral (263ms)
      ✓ withdrawColl(): reduces the Trove's collateral by the correct amount (316ms)
      ✓ withdrawColl(): reduces ActivePool REEF and raw ether by correct amount (291ms)
      ✓ withdrawColl(): updates the stake and updates the total stakes (342ms)
      ✓ withdrawColl(): sends the correct amount of REEF to the user (289ms)
      ✓ withdrawColl(): applies pending rewards and updates user's L_ETH, L_MoUSDDebt snapshots (1205ms)
      ✓ withdrawMoUSD(): reverts when withdrawal would leave trove with ICR < MCR (516ms)
      ✓ withdrawMoUSD(): decays a non-zero base rate (1192ms)
      ✓ withdrawMoUSD(): reverts if max fee > 100% (668ms)
      ✓ withdrawMoUSD(): reverts if max fee < 0.5% in Normal mode (639ms)
      ✓ withdrawMoUSD(): reverts if fee exceeds max fee percentage (938ms)
      ✓ withdrawMoUSD(): succeeds when fee is less than max fee percentage (1272ms)
      ✓ withdrawMoUSD(): doesn't change base rate if it is already zero (1044ms)
      ✓ withdrawMoUSD(): lastFeeOpTime doesn't update if less time than decay interval has passed since the last fee operation (899ms)
      ✓ withdrawMoUSD(): borrower can't grief the baseRate and stop it decaying by issuing debt at higher frequency than the decay granularity (852ms)
      ✓ withdrawMoUSD(): borrowing at non-zero base rate sends MoUSD fee to MSIC staking contract (1004ms)
      ✓ withdrawMoUSD(): borrowing at non-zero base records the (drawn debt + fee) on the Trove struct (923ms)
      ✓ withdrawMoUSD(): Borrowing at non-zero base rate increases the MSIC staking contract MoUSD fees-per-unit-staked (986ms)
      ✓ withdrawMoUSD(): Borrowing at non-zero base rate sends requested amount to the user (1562ms)
      ✓ withdrawMoUSD(): Borrowing at zero base rate changes MoUSD fees-per-unit-staked (839ms)
      ✓ withdrawMoUSD(): Borrowing at zero base rate sends debt request to user (790ms)
      ✓ withdrawMoUSD(): reverts when calling address does not have active trove (370ms)
      ✓ withdrawMoUSD(): reverts when requested withdrawal amount is zero MoUSD (459ms)
      ✓ withdrawMoUSD(): reverts when system is in Recovery Mode (649ms)
      ✓ withdrawMoUSD(): reverts when withdrawal would bring the trove's ICR < MCR (347ms)
      ✓ withdrawMoUSD(): reverts when a withdrawal would cause the TCR of the system to fall below the CCR (439ms)
      ✓ withdrawMoUSD(): reverts if system is in Recovery Mode (312ms)
      ✓ withdrawMoUSD(): increases the Trove's MoUSD debt by the correct amount (208ms)
      ✓ withdrawMoUSD(): increases MoUSD debt in ActivePool by correct amount (230ms)
      ✓ withdrawMoUSD(): increases user MoUSDToken balance by correct amount (243ms)
      ✓ repayMoUSD(): reverts when repayment would leave trove with ICR < MCR (392ms)
      ✓ repayMoUSD(): Succeeds when it would leave trove with net debt >= minimum net debt (435ms)
      ✓ repayMoUSD(): reverts when it would leave trove with net debt < minimum net debt (256ms)
      ✓ repayMoUSD(): reverts when calling address does not have active trove (431ms)
      ✓ repayMoUSD(): reverts when attempted repayment is > the debt of the trove (418ms)
      ✓ repayMoUSD(): reduces the Trove's MoUSD debt by the correct amount (403ms)
      ✓ repayMoUSD(): decreases MoUSD debt in ActivePool by correct amount (406ms)
      ✓ repayMoUSD(): decreases user MoUSDToken balance by correct amount (404ms)
      ✓ repayMoUSD(): can repay debt in Recovery Mode (557ms)
      ✓ repayMoUSD(): Reverts if borrower has insufficient MoUSD balance to cover his debt repayment (1122ms)
      ✓ adjustTrove(): reverts when adjustment would leave trove with ICR < MCR (572ms)
      ✓ adjustTrove(): reverts if max fee < 0.5% in Normal mode (313ms)
      ✓ adjustTrove(): allows max fee < 0.5% in Recovery mode (577ms)
      ✓ adjustTrove(): decays a non-zero base rate (1218ms)
      ✓ adjustTrove(): doesn't decay a non-zero base rate when user issues 0 debt (935ms)
      ✓ adjustTrove(): doesn't change base rate if it is already zero (545ms)
      ✓ adjustTrove(): lastFeeOpTime doesn't update if less time than decay interval has passed since the last fee operation (819ms)
      ✓ adjustTrove(): borrower can't grief the baseRate and stop it decaying by issuing debt at higher frequency than the decay granularity (866ms)
      ✓ adjustTrove(): borrowing at non-zero base rate sends MoUSD fee to MSIC staking contract (889ms)
      ✓ adjustTrove(): borrowing at non-zero base records the (drawn debt + fee) on the Trove struct (1013ms)
      ✓ adjustTrove(): Borrowing at non-zero base rate increases the MSIC staking contract MoUSD fees-per-unit-staked (837ms)
      ✓ adjustTrove(): Borrowing at non-zero base rate sends requested amount to the user (895ms)
      ✓ adjustTrove(): Borrowing at zero base rate changes MoUSD balance of MSIC staking contract (783ms)
      ✓ adjustTrove(): Borrowing at zero base rate changes MSIC staking contract MoUSD fees-per-unit-staked (881ms)
      ✓ adjustTrove(): Borrowing at zero base rate sends total requested MoUSD to the user (783ms)
      ✓ adjustTrove(): reverts when calling address has no active trove (416ms)
      ✓ adjustTrove(): reverts in Recovery Mode when the adjustment would reduce the TCR (654ms)
      ✓ adjustTrove(): collateral withdrawal reverts in Recovery Mode (370ms)
      ✓ adjustTrove(): debt increase that would leave ICR < 150% reverts in Recovery Mode (497ms)
      ✓ adjustTrove(): debt increase that would reduce the ICR reverts in Recovery Mode (596ms)
      ✓ adjustTrove(): A trove with ICR < CCR in Recovery Mode can adjust their trove to ICR > CCR (599ms)
      ✓ adjustTrove(): A trove with ICR > CCR in Recovery Mode can improve their ICR (524ms)
      ✓ adjustTrove(): debt increase in Recovery Mode charges no fee (543ms)
      ✓ adjustTrove(): reverts when change would cause the TCR of the system to fall below the CCR (587ms)
      ✓ adjustTrove(): reverts when MoUSD repaid is > debt of the trove (451ms)
      ✓ adjustTrove(): reverts when attempted REEF withdrawal is >= the trove's collateral (683ms)
      ✓ adjustTrove(): reverts when change would cause the ICR of the trove to fall below the MCR (521ms)
      ✓ adjustTrove(): With 0 coll change, doesnt change borrower's coll or ActivePool coll (289ms)
      ✓ adjustTrove(): With 0 debt change, doesnt change borrower's debt or ActivePool debt (354ms)
      ✓ adjustTrove(): updates borrower's debt and coll with an increase in both (558ms)
      ✓ adjustTrove(): updates borrower's debt and coll with a decrease in both (553ms)
      ✓ adjustTrove(): updates borrower's  debt and coll with coll increase, debt decrease (375ms)
      ✓ adjustTrove(): updates borrower's debt and coll with coll decrease, debt increase (346ms)
      ✓ adjustTrove(): updates borrower's stake and totalStakes with a coll increase (385ms)
      ✓ adjustTrove():  updates borrower's stake and totalStakes with a coll decrease (553ms)
      ✓ adjustTrove(): changes MoUSDToken balance by the requested decrease (529ms)
      ✓ adjustTrove(): changes MoUSDToken balance by the requested increase (577ms)
      ✓ adjustTrove(): Changes the activePool REEF and raw ether balance by the requested decrease (1371ms)
      ✓ adjustTrove(): Changes the activePool REEF and raw ether balance by the amount of REEF sent (548ms)
      ✓ adjustTrove(): Changes the MoUSD debt in ActivePool by requested decrease (541ms)
      ✓ adjustTrove(): Changes the MoUSD debt in ActivePool by requested increase (397ms)
      ✓ adjustTrove(): new coll = 0 and new debt = 0 is not allowed, as gas compensation still counts toward ICR (385ms)
      ✓ adjustTrove(): Reverts if requested debt increase and amount is zero (292ms)
      ✓ adjustTrove(): Reverts if requested coll withdrawal and ether is sent (288ms)
      ✓ adjustTrove(): Reverts if it’s zero adjustment (137ms)
      ✓ adjustTrove(): Reverts if requested coll withdrawal is greater than trove's collateral (402ms)
      ✓ adjustTrove(): Reverts if borrower has insufficient MoUSD balance to cover his debt repayment (496ms)
      ✓ Internal _adjustTrove(): reverts when op is a withdrawal and _borrower param is not the msg.sender (475ms)
      ✓ closeTrove(): reverts when it would lower the TCR below CCR (471ms)
      ✓ closeTrove(): reverts when calling address does not have active trove (221ms)
      ✓ closeTrove(): reverts when system is in Recovery Mode (746ms)
      ✓ closeTrove(): reverts when trove is the only one in the system (497ms)
      ✓ closeTrove(): reduces a Trove's collateral to zero (582ms)
      ✓ closeTrove(): reduces a Trove's debt to zero (398ms)
      ✓ closeTrove(): sets Trove's stake to zero (504ms)
      ✓ closeTrove(): zero's the troves reward snapshots (1002ms)
      ✓ closeTrove(): sets trove's status to closed and removes it from sorted troves list (526ms)
      ✓ closeTrove(): reduces ActivePool REEF and raw ether by correct amount (466ms)
      ✓ closeTrove(): reduces ActivePool debt by correct amount (522ms)
      ✓ closeTrove(): updates the the total stakes (790ms)
      ✓ closeTrove(): sends the correct amount of REEF to the user (390ms)
      ✓ closeTrove(): subtracts the debt of the closed Trove from the Borrower's MoUSDToken balance (405ms)
      ✓ closeTrove(): applies pending rewards (1267ms)
      ✓ closeTrove(): reverts if borrower has insufficient MoUSD balance to repay his entire debt (347ms)
      ✓ openTrove(): emits a TroveUpdated event with the correct collateral and debt (820ms)
      ✓ openTrove(): Opens a trove with net debt >= minimum net debt (235ms)
      ✓ openTrove(): reverts if net debt < minimum net debt (294ms)
      ✓ openTrove(): decays a non-zero base rate (959ms)
      ✓ openTrove(): doesn't change base rate if it is already zero (911ms)
      ✓ openTrove(): lastFeeOpTime doesn't update if less time than decay interval has passed since the last fee operation (953ms)
      ✓ openTrove(): reverts if max fee > 100% (56ms)
      ✓ openTrove(): reverts if max fee < 0.5% in Normal mode (85ms)
      ✓ openTrove(): allows max fee < 0.5% in Recovery Mode (409ms)
      ✓ openTrove(): reverts if fee exceeds max fee percentage (747ms)
      ✓ openTrove(): succeeds when fee is less than max fee percentage (930ms)
      ✓ openTrove(): borrower can't grief the baseRate and stop it decaying by issuing debt at higher frequency than the decay granularity (965ms)
      ✓ openTrove(): borrowing at non-zero base rate sends MoUSD fee to MSIC staking contract (923ms)
      ✓ openTrove(): borrowing at non-zero base records the (drawn debt + fee  + liq. reserve) on the Trove struct (865ms)
      ✓ openTrove(): Borrowing at non-zero base rate increases the MSIC staking contract MoUSD fees-per-unit-staked (794ms)
      ✓ openTrove(): Borrowing at non-zero base rate sends requested amount to the user (832ms)
      ✓ openTrove(): Borrowing at zero base rate changes the MSIC staking contract MoUSD fees-per-unit-staked (602ms)
      ✓ openTrove(): Borrowing at zero base rate charges minimum fee (316ms)
      ✓ openTrove(): reverts when system is in Recovery Mode and ICR < CCR (320ms)
      ✓ openTrove(): reverts when trove ICR < MCR (536ms)
      ✓ openTrove(): reverts when opening the trove would cause the TCR of the system to fall below the CCR (367ms)
      ✓ openTrove(): reverts if trove is already active (679ms)
      ✓ openTrove(): Can open a trove with ICR >= CCR when system is in Recovery Mode (499ms)
      ✓ openTrove(): Reverts opening a trove with min debt when system is in Recovery Mode (324ms)
      ✓ openTrove(): creates a new Trove and assigns the correct collateral and debt amount (127ms)
      ✓ openTrove(): adds Trove owner to TroveOwners array (136ms)
      ✓ openTrove(): creates a stake and adds it to total stakes (281ms)
      ✓ openTrove(): inserts Trove to Sorted Troves list (370ms)
      ✓ openTrove(): Increases the activePool REEF and raw ether balance by correct amount (294ms)
      ✓ openTrove(): records up-to-date initial snapshots of L_ETH and L_MoUSDDebt (639ms)
      ✓ openTrove(): allows a user to open a Trove, then close it, then re-open it (687ms)
      ✓ openTrove(): increases the Trove's MoUSD debt by the correct amount (129ms)
      ✓ openTrove(): increases MoUSD debt in ActivePool by the debt of the trove (162ms)
      ✓ openTrove(): increases user MoUSDToken balance by correct amount (85ms)
      ✓ getCompositeDebt(): returns debt + gas comp
      ✓ closeTrove(): fails if owner cannot receive REEF (440ms)
      getNewICRFromTroveChange() returns the correct ICR
        ✓ collChange = 0, debtChange = 0
        ✓ collChange = 0, debtChange is positive
        ✓ collChange = 0, debtChange is negative
        ✓ collChange is positive, debtChange is 0
        ✓ collChange is negative, debtChange is 0
        ✓ collChange is negative, debtChange is negative
        ✓ collChange is positive, debtChange is positive
        ✓ collChange is positive, debtChange is negative
        ✓ collChange is negative, debtChange is positive
      getNewTCRFromTroveChange() returns the correct TCR
        ✓ collChange = 0, debtChange = 0 (248ms)
        ✓ collChange = 0, debtChange is positive (630ms)
        ✓ collChange = 0, debtChange is negative (327ms)
        ✓ collChange is positive, debtChange is 0 (328ms)
        ✓ collChange is negative, debtChange is 0 (407ms)
        ✓ collChange is negative, debtChange is negative (605ms)
        ✓ collChange is positive, debtChange is positive (601ms)
        ✓ collChange is positive, debtChange is negative (609ms)
        ✓ collChange is negative, debtChange is positive (381ms)

  Contract: CollSurplusPool
    ✓ CollSurplusPool::getETH(): Returns the REEF balance of the CollSurplusPool after redemption (2203ms)
    ✓ CollSurplusPool: claimColl(): Reverts if caller is not Borrower Operations
    ✓ CollSurplusPool: claimColl(): Reverts if nothing to claim
    ✓ CollSurplusPool: claimColl(): Reverts if owner cannot receive REEF surplus (723ms)
    ✓ CollSurplusPool: reverts trying to send REEF to it
    ✓ CollSurplusPool: accountSurplus: reverts if caller is not Trove Manager

  Contract: Deployment script - Sets correct contract addresses dependencies after deployment
    ✓ Sets the correct PriceFeed address in TroveManager
    ✓ Sets the correct MoUSDToken address in TroveManager
    ✓ Sets the correct SortedTroves address in TroveManager
    ✓ Sets the correct BorrowerOperations address in TroveManager
    ✓ Sets the correct ActivePool address in TroveManager
    ✓ Sets the correct DefaultPool address in TroveManager
    ✓ Sets the correct StabilityPool address in TroveManager
    ✓ Sets the correct MSICStaking address in TroveManager
    ✓ Sets the correct StabilityPool address in ActivePool
    ✓ Sets the correct DefaultPool address in ActivePool (133ms)
    ✓ Sets the correct BorrowerOperations address in ActivePool
    ✓ Sets the correct TroveManager address in ActivePool
    ✓ Sets the correct ActivePool address in StabilityPool
    ✓ Sets the correct BorrowerOperations address in StabilityPool
    ✓ Sets the correct MoUSDToken address in StabilityPool
    ✓ Sets the correct TroveManager address in StabilityPool
    ✓ Sets the correct TroveManager address in DefaultPool
    ✓ Sets the correct ActivePool address in DefaultPool
    ✓ Sets the correct TroveManager address in SortedTroves
    ✓ Sets the correct BorrowerOperations address in SortedTroves
    ✓ Sets the correct TroveManager address in BorrowerOperations
    ✓ Sets the correct PriceFeed address in BorrowerOperations
    ✓ Sets the correct SortedTroves address in BorrowerOperations
    ✓ Sets the correct ActivePool address in BorrowerOperations
    ✓ Sets the correct DefaultPool address in BorrowerOperations
    ✓ Sets the correct MSICStaking address in BorrowerOperations
    ✓ Sets the correct MSICToken address in MSICStaking
    ✓ Sets the correct ActivePool address in MSICStaking
    ✓ Sets the correct ActivePool address in MSICStaking
    ✓ Sets the correct ActivePool address in MSICStaking
    ✓ Sets the correct BorrowerOperations address in MSICStaking
    ✓ Sets the correct CommunityIssuance address in MSICToken
    ✓ Sets the correct MSICStaking address in MSICToken
    ✓ Sets the correct LockupContractFactory address in MSICToken
    ✓ Sets the correct MSICToken address in LockupContractFactory
    ✓ Sets the correct MSICToken address in CommunityIssuance
    ✓ Sets the correct StabilityPool address in CommunityIssuance

  Contract: DefaultPool
    ✓ sendETHToActivePool(): fails if receiver cannot receive REEF

  Contract: Fee arithmetic tests
    ✓ minutesPassedSinceLastFeeOp(): returns minutes passed for no time increase (197ms)
    ✓ minutesPassedSinceLastFeeOp(): returns minutes passed between time of last fee operation and current block.timestamp, rounded down to nearest minutes (982ms)
    ✓ decayBaseRateFromBorrowing(): returns the initial base rate for no time increase
    ✓ decayBaseRateFromBorrowing(): returns the initial base rate for less than one minute passed  (386ms)
    ✓ decayBaseRateFromBorrowing(): returns correctly decayed base rate, for various durations. Initial baseRate = 0.01 (2908ms)
    ✓ decayBaseRateFromBorrowing(): returns correctly decayed base rate, for various durations. Initial baseRate = 0.1 (3951ms)
    ✓ decayBaseRateFromBorrowing(): returns correctly decayed base rate, for various durations. Initial baseRate = 0.34539284 (3651ms)
    ✓ decayBaseRateFromBorrowing(): returns correctly decayed base rate, for various durations. Initial baseRate = 0.9976 (4377ms)
    Basic exponentiation
      ✓ decPow(): for exponent = 0, returns 1, regardless of base (42ms)
      ✓ decPow(): for exponent = 1, returns base, regardless of base (86ms)
      ✓ decPow(): for base = 0, returns 0 for any exponent other than 0 (238ms)
      ✓ decPow(): for base = 1, returns 1 for any exponent (179ms)
      ✓ decPow(): for exponent = 2, returns the square of the base (86ms)
      ✓ decPow(): correct output for various bases and exponents (2032ms)
      ✓ decPow(): abs. error < 1e-9 for exponent = 7776000 (seconds in three months) (8459ms)
      ✓ decPow(): abs. error < 1e-9 for exponent = 2592000 (seconds in one month) (4815ms)
      ✓ decPow(): abs. error < 1e-9 for exponent = 43200 (minutes in one month) (4387ms)
      ✓ decPow(): abs. error < 1e-9 for exponent = 525600 (minutes in one year) (4454ms)
      ✓ decPow(): abs. error < 1e-9 for exponent = 2628000 (minutes in five years) (4724ms)
      ✓ decPow(): abs. error < 1e-9 for exponent = minutes in ten years (3847ms)
      ✓ decPow(): abs. error < 1e-9 for exponent = minutes in one hundred years (5802ms)
      - decPow(): overflow test: doesn't overflow for exponent = minutes in 1000 years

  Contract: Gas compensation tests
    ✓ _getCollGasCompensation(): returns the 0.5% of collaterall if it is < $10 in value
    ✓ _getCollGasCompensation(): returns 0.5% of collaterall when 0.5% of collateral < $10 in value
    ✓ getCollGasCompensation(): returns 0.5% of collaterall when 0.5% of collateral = $10 in value
    ✓ getCollGasCompensation(): returns 0.5% of collaterall when 0.5% of collateral = $10 in value (72ms)
    ✓ _getCompositeDebt(): returns (debt + 50) when collateral < $10 in value
    ✓ getCompositeDebt(): returns (debt + 50) collateral = $10 in value
    ✓ getCompositeDebt(): returns (debt + 50) when 0.5% of collateral > $10 in value (52ms)
    ✓ getCurrentICR(): Incorporates virtual debt, and returns the correct ICR for new troves (1147ms)
    ✓ Gas compensation from pool-offset liquidations. All collateral paid as compensation (1340ms)
    ✓ gas compensation from pool-offset liquidations: 0.5% collateral < $10 in value. Compensates $10 worth of collateral, liquidates the remainder (1199ms)
    ✓ gas compensation from pool-offset liquidations: 0.5% collateral > $10 in value. Compensates 0.5% of  collateral, liquidates the remainder (1333ms)
TCR: 238.086389539884110295
TCR: 11.892415157517211309
    ✓ Gas compensation from pool-offset liquidations. Liquidation event emits the correct gas compensation and total liquidated coll and debt (1541ms)
    ✓ gas compensation from pool-offset liquidations. Liquidation event emits the correct gas compensation and total liquidated coll and debt (1498ms)
    ✓ gas compensation from pool-offset liquidations: 0.5% collateral > $10 in value. Liquidation event emits the correct gas compensation and total liquidated coll and debt (1547ms)
    ✓ liquidateTroves(): full offset.  Compensates the correct amount, and liquidates the remainder (1810ms)
    ✓ liquidateTroves(): full redistribution. Compensates the correct amount, and liquidates the remainder (1312ms)
    ✓ liquidateTroves(): full offset. Liquidation event emits the correct gas compensation and total liquidated coll and debt (1551ms)
    ✓ liquidateTroves(): full redistribution. Liquidation event emits the correct gas compensation and total liquidated coll and debt (1790ms)
    ✓ Trove ordering: same collateral, decreasing debt. Price successively increases. Troves should maintain ordering by ICR (1647ms)
    ✓ Trove ordering: increasing collateral, constant debt. Price successively increases. Troves should maintain ordering by ICR (3885ms)
    ✓ Trove ordering: Constant raw collateral ratio (excluding virtual debt). Price successively increases. Troves should maintain ordering by ICR (2042ms)

  Contract: MSIC Token
    ✓ balanceOf(): gets the balance of the account (43ms)
    ✓ totalSupply(): gets the total supply
    ✓ name(): returns the token's name
    ✓ symbol(): returns the token's symbol
    ✓ version(): returns the token contract's version
    ✓ decimal(): returns the number of decimal digits used
    ✓ allowance(): returns an account's spending allowance for another account's balance (48ms)
    ✓ approve(): approves an account to spend the specified ammount (47ms)
    ✓ approve(): reverts when spender param is address(0) (52ms)
    ✓ approve(): reverts when owner param is address(0) (60ms)
    ✓ transferFrom(): successfully transfers from an account which it is approved to transfer from (123ms)
    ✓ transfer(): increases the recipient's balance by the correct amount (42ms)
    ✓ transfer(): reverts when amount exceeds sender's balance (56ms)
    ✓ transfer(): transfer to a blacklisted address reverts (204ms)
    ✓ transfer(): transfer to or from the zero-address reverts (49ms)
    ✓ mint(): issues correct amount of tokens to the given address
    ✓ mint(): reverts when beneficiary is address(0)
    ✓ increaseAllowance(): increases an account's allowance by the correct amount
    ✓ decreaseAllowance(): decreases an account's allowance by the correct amount
    ✓ sendToMSICStaking(): changes balances of MSICStaking and calling account by the correct amounts (48ms)
    ✓ Initializes PERMIT_TYPEHASH correctly
    ✓ Initializes DOMAIN_SEPARATOR correctly
    ✓ Initial nonce for a given address is 0
    ✓ permit(): permits and emits an Approval event (replay protected) (88ms)
    ✓ permit(): fails with expired deadline
    ✓ permit(): fails with the wrong signature (46ms)

  Contract: HintHelpers
    ✓ setup: makes accounts with nominal ICRs increasing by 1% consecutively (76ms)
    ✓ getApproxHint(): returns the address of a Trove within sqrt(length) positions of the correct insert position (1441ms)
    ✓ getApproxHint(): returns the head of the list if the CR is the max uint256 value (270ms)
    ✓ getApproxHint(): returns the tail of the list if the CR is lower than ICR of any Trove (321ms)
    ✓ computeNominalCR()

  Contract: Deploying and funding One Year Lockup Contracts
    Deploying LCs
      ✓ MSIC Deployer can deploy LCs through the Factory (121ms)
      ✓ Anyone can deploy LCs through the Factory (71ms)
      ✓ MSIC Deployer can deploy LCs directly (43ms)
      ✓ Anyone can deploy LCs directly (43ms)
      ✓ LC deployment stores the beneficiary's address in the LC (1806ms)
      ✓ LC deployment through the Factory registers the LC in the Factory (99ms)
      ✓ LC deployment through the Factory records the LC contract address and deployer as a k-v pair in the Factory (90ms)
      ✓ LC deployment through the Factory sets the unlockTime in the LC (52ms)
      ✓ Direct deployment of LC sets the unlockTime in the LC (55ms)
      ✓ LC deployment through the Factory reverts when the unlockTime is < 1 year from system deployment (50ms)
      ✓ Direct deployment of LC reverts when the unlockTime is < 1 year from system deployment (54ms)
    Funding LCs
      ✓ MSIC transfer from MSIC deployer to their deployed LC increases the MSIC balance of the LC (397ms)
      ✓ MSIC Multisig can transfer MSIC to LCs deployed through the factory by anyone (168ms)
    Withdrawal attempts on funded, inactive LCs immediately after funding
      ✓ Beneficiary can't withdraw from their funded LC (346ms)
      ✓ MSIC multisig can't withraw from a LC which it funded (271ms)
      ✓ No one can withraw from a LC (78ms)

  Contract: Deploying the MSIC contracts: LCF, CI, MSICStaking, and MSICToken 
    CommunityIssuance deployment
      ✓ Stores the deployer's address
    MSICStaking deployment
      ✓ Stores the deployer's address
    MSICToken deployment
      ✓ Stores the multisig's address
      ✓ Stores the CommunityIssuance address
      ✓ Stores the LockupContractFactory address
      ✓ Mints the correct MSIC amount to the multisig's address: (64.66 million)
      ✓ Mints the correct MSIC amount to the CommunityIssuance contract address: 32 million
      ✓ Mints the correct MSIC amount to the bountyAddress EOA: 2 million
      ✓ Mints the correct MSIC amount to the lpRewardsAddress EOA: 1.33 million
    Community Issuance deployment
      ✓ Stores the deployer's address
      ✓ Has a supply cap of 32 million
      ✓ Mosaic AG can set addresses if CI's MSIC balance is equal or greater than 32 million  (393ms)
      ✓ Mosaic AG can't set addresses if CI's MSIC balance is < 32 million  (367ms)
    Connecting MSICToken to LCF, CI and MSICStaking
      ✓ sets the correct MSICToken address in MSICStaking (1866ms)
      ✓ sets the correct MSICToken address in LockupContractFactory
      ✓ sets the correct MSICToken address in CommunityIssuance (203ms)

  Contract: During the initial lockup period
    MSIC transfer during first year after MSIC deployment
      ✓ Mosaic multisig can not transfer MSIC to a LC that was deployed directly (105ms)
      ✓ Mosaic multisig can not transfer to an EOA or Mosaic system contracts (302ms)
      ✓ Mosaic multisig can not approve any EOA or Mosaic system contract to spend their MSIC (546ms)
      ✓ Mosaic multisig can not increaseAllowance for any EOA or Mosaic contract (285ms)
      ✓ Mosaic multisig can not decreaseAllowance for any EOA or Mosaic contract (338ms)
      ✓ Mosaic multisig can not be the sender in a transferFrom() call
      ✓ Mosaic multisig can not stake their MSIC in the staking contract
      ✓ Anyone (other than Mosaic multisig) can transfer MSIC to LCs deployed by anyone through the Factory (359ms)
      ✓ Anyone (other than Mosaic multisig) can transfer MSIC to LCs deployed by anyone directly (141ms)
      ✓ Anyone (other than mosaic multisig) can transfer to an EOA (106ms)
      ✓ Anyone (other than mosaic multisig) can approve any EOA or to spend their MSIC
      ✓ Anyone (other than mosaic multisig) can increaseAllowance for any EOA or Mosaic contract (244ms)
      ✓ Anyone (other than mosaic multisig) can decreaseAllowance for any EOA or Mosaic contract (693ms)
      ✓ Anyone (other than mosaic multisig) can be the sender in a transferFrom() call (62ms)
      ✓ Anyone (other than mosaic AG) can stake their MSIC in the staking contract
    Lockup Contract Factory negative tests
      ✓ deployLockupContract(): reverts when MSIC token address is not set (197ms)
    Transferring MSIC to LCs
      ✓ Mosaic multisig can transfer MSIC (vesting) to lockup contracts they deployed (198ms)
      ✓ Mosaic multisig can transfer MSIC to lockup contracts deployed by anyone (1798ms)
    Deploying new LCs
      ✓ MSIC Deployer can deploy LCs through the Factory (46ms)
      ✓ Mosaic multisig can deploy LCs through the Factory
      ✓ Anyone can deploy LCs through the Factory (80ms)
      ✓ MSIC Deployer can deploy LCs directly (44ms)
      ✓ Mosaic multisig can deploy LCs directly (45ms)
      ✓ Anyone can deploy LCs directly (46ms)
      ✓ Anyone can deploy LCs with unlockTime = one year from deployment, directly and through factory (102ms)
      ✓ Anyone can deploy LCs with unlockTime > one year from deployment, directly and through factory (187ms)
      ✓ No one can deploy LCs with unlockTime < one year from deployment, directly or through factory (100ms)
      Withdrawal Attempts on LCs before unlockTime has passed 
        ✓ Mosaic multisig can't withdraw from a funded LC they deployed for another beneficiary through the Factory before the unlockTime
        ✓ Mosaic multisig can't withdraw from a funded LC that someone else deployed before the unlockTime (52ms)
        ✓ Beneficiary can't withdraw from their funded LC before the unlockTime (219ms)
        ✓ No one can withdraw from a beneficiary's funded LC before the unlockTime (475ms)

  Contract: After the initial lockup period has passed
    Deploying new LCs
      ✓ MSIC Deployer can deploy new LCs
      ✓ Anyone can deploy new LCs (42ms)
      ✓ Anyone can deploy new LCs with unlockTime in the past (65ms)
      ✓ Anyone can deploy new LCs with unlockTime in the future (46ms)
    Beneficiary withdrawal from initial LC
      ✓ A beneficiary can withdraw their full entitlement from their LC (256ms)
      ✓ A beneficiary on a vesting schedule can withdraw their total vested amount from their LC (155ms)
      ✓ Beneficiaries can withraw full MSIC balance of LC if it has increased since lockup period ended (234ms)
    Withdrawal attempts from LCs by non-beneficiaries
      ✓ MSIC Multisig can't withdraw from a LC they deployed through the Factory
      ✓ MSIC Multisig can't withdraw from a LC that someone else deployed
      ✓ Non-beneficiaries cannot withdraw from a LC (189ms)
    Transferring MSIC
      ✓ MSIC multisig can transfer MSIC to LCs they deployed (176ms)
      ✓ MSIC multisig can transfer tokens to LCs deployed by anyone (104ms)
      ✓ MSIC multisig can transfer MSIC directly to any externally owned account (141ms)
      ✓ Anyone can transfer MSIC to LCs deployed by anyone (179ms)
      ✓ Anyone can transfer to an EOA (421ms)
      ✓ Anyone can approve any EOA to spend their MSIC
      ✓ Anyone can increaseAllowance for any EOA or Mosaic contract (2441ms)
      ✓ Anyone can decreaseAllowance for any EOA or Mosaic contract (1034ms)
      ✓ Anyone can be the sender in a transferFrom() call (101ms)
      ✓ Anyone can stake their MSIC in the staking contract (55ms)
    Withdrawal Attempts on new LCs before unlockTime has passed
      ✓ MSIC Deployer can't withdraw from a funded LC they deployed for another beneficiary through the Factory, before the unlockTime (44ms)
      ✓ MSIC Deployer can't withdraw from a funded LC that someone else deployed, before the unlockTime (448ms)
      ✓ Beneficiary can't withdraw from their funded LC, before the unlockTime (284ms)
      ✓ No one can withdraw from a beneficiary's funded LC, before the unlockTime (443ms)
    Withdrawals from new LCs after unlockTime has passed
      ✓ MSIC Deployer can't withdraw from a funded LC they deployed for another beneficiary through the Factory, after the unlockTime (100ms)
      ✓ MSIC multisig can't withdraw from a funded LC when they are not the beneficiary, after the unlockTime (529ms)
      ✓ Beneficiary can withdraw from their funded LC, after the unlockTime (97ms)
      ✓ Non-beneficiaries can't withdraw from a beneficiary's funded LC, after the unlockTime (226ms)

  Contract: MosaicMath
    ✓ max works if a > b
    ✓ max works if a = b
    ✓ max works if a < b

  Contract: MosaicSafeMath128Tester
    ✓ add(): reverts if overflows
    ✓ sub(): reverts if underflows

  Contract: MSIC community issuance arithmetic tests
issuance fraction before: 949066037374286
issuance fraction after: 949066037374286
    ✓ getCumulativeIssuanceFraction(): fraction doesn't increase if less than a minute has passed (45ms)
    ✓ Cumulative issuance fraction is 0.0000013 after a minute
    ✓ Cumulative issuance fraction is 0.000079 after an hour
    ✓ Cumulative issuance fraction is 0.0019 after a day
    ✓ Cumulative issuance fraction is 0.013 after a week (283ms)
    ✓ Cumulative issuance fraction is 0.055 after a month (38ms)
    ✓ Cumulative issuance fraction is 0.16 after 3 months
    ✓ Cumulative issuance fraction is 0.29 after 6 months (38ms)
    ✓ Cumulative issuance fraction is 0.5 after a year
    ✓ Cumulative issuance fraction is 0.75 after 2 years
    ✓ Cumulative issuance fraction is 0.875 after 3 years (44ms)
    ✓ Cumulative issuance fraction is 0.9375 after 4 years (50ms)
    ✓ Cumulative issuance fraction is 0.999 after 10 years
    ✓ Cumulative issuance fraction is 0.999999 after 20 years (78ms)
    ✓ Cumulative issuance fraction is 0.999999999 after 30 years (55ms)
    ✓ Total MSIC tokens issued is 42.20 after a minute (38ms)
    ✓ Total MSIC tokens issued is 2,531.94 after an hour (41ms)
    ✓ Total MSIC tokens issued is 60,711.40 after a day (136ms)
    ✓ Total MSIC tokens issued is 422,568.60 after a week (331ms)
    ✓ Total MSIC tokens issued is 1,772,113.21 after a month
    ✓ Total MSIC tokens issued is 5,027,363.22 after 3 months (40ms)
    ✓ Total MSIC tokens issued is 9,264,902.04 after 6 months (47ms)
    ✓ Total MSIC tokens issued is 16,000,000 after a year (47ms)
    ✓ Total MSIC tokens issued is 24,000,000 after 2 years (47ms)
    ✓ Total MSIC tokens issued is 28,000,000 after 3 years (75ms)
    ✓ Total MSIC tokens issued is 30,000,000 after 4 years (40ms)
    ✓ Total MSIC tokens issued is 31,968,750 after 10 years (69ms)
    ✓ Total MSIC tokens issued is 31,999,969.48 after 20 years (68ms)
    ✓ Total MSIC tokens issued is 31,999,999.97 after 30 years (87ms)
    - Frequent token issuance: issuance event every year, for 30 years
    - Frequent token issuance: issuance event every day, for 30 years
    - Frequent token issuance: issuance event every minute, for 1 month
    - Frequent token issuance: issuance event every minute, for 1 year

  Contract: MSICStaking revenue share tests
    ✓ stake(): reverts if amount is zero (74ms)
    ✓ REEF fee per MSIC staked increases when a redemption fee is triggered and totalStakes > 0 (1562ms)
    ✓ REEF fee per MSIC staked doesn't change when a redemption fee is triggered and totalStakes == 0 (3540ms)
    ✓ MoUSD fee per MSIC staked increases when a redemption fee is triggered and totalStakes > 0 (1757ms)
    ✓ MoUSD fee per MSIC staked doesn't change when a redemption fee is triggered and totalStakes == 0 (1705ms)
    ✓ MSIC Staking: A single staker earns all REEF and MSIC fees that occur (2143ms)
    ✓ stake(): Top-up sends out all accumulated REEF and MoUSD gains to the staker (2138ms)
    ✓ getPendingETHGain(): Returns the staker's correct pending REEF gain (1856ms)
    ✓ getPendingMoUSDGain(): Returns the staker's correct pending MoUSD gain (1965ms)
    ✓ MSIC Staking: Multiple stakers earn the correct share of all REEF and MSIC fees, based on their stake size (3133ms)
    ✓ unstake(): reverts if caller has REEF gains and can't receive REEF (1149ms)
    ✓ receive(): reverts when it receives REEF from an address that is not the Active Pool
    ✓ unstake(): reverts if user has no stake
    ✓ Test requireCallerIsTroveManager

  Contract: MoUSDToken
    Basic token functions, without Proxy
      ✓ balanceOf(): gets the balance of the account
      ✓ totalSupply(): gets the total supply
      ✓ name(): returns the token's name
      ✓ symbol(): returns the token's symbol
      ✓ decimal(): returns the number of decimal digits used
      ✓ allowance(): returns an account's spending allowance for another account's balance (77ms)
      ✓ approve(): approves an account to spend the specified amount
      ✓ approve(): reverts when spender param is address(0)
      ✓ approve(): reverts when owner param is address(0)
      ✓ transferFrom(): successfully transfers from an account which is it approved to transfer from (272ms)
      ✓ transfer(): increases the recipient's balance by the correct amount
      ✓ transfer(): reverts if amount exceeds sender's balance
      ✓ transfer(): transferring to a blacklisted address reverts (79ms)
      ✓ increaseAllowance(): increases an account's allowance by the correct amount (94ms)
      ✓ mint(): issues correct amount of tokens to the given address
      ✓ burn(): burns correct amount of tokens from the given address
      ✓ sendToPool(): changes balances of Stability pool and user by the correct amounts
      ✓ returnFromPool(): changes balances of Stability pool and user by the correct amounts (39ms)
      ✓ transfer(): transferring to a blacklisted address reverts (76ms)
      ✓ decreaseAllowance(): decreases allowance by the expected amount (38ms)
      ✓ decreaseAllowance(): fails trying to decrease more than previously allowed (39ms)
      ✓ version(): returns the token contract's version
      ✓ Initializes PERMIT_TYPEHASH correctly
      ✓ Initializes DOMAIN_SEPARATOR correctly
      ✓ Initial nonce for a given address is 0
      ✓ permits and emits an Approval event (replay protected) (69ms)
      ✓ permits(): fails with expired deadline (59ms)
      ✓ permits(): fails with the wrong signature (51ms)
    Basic token functions, with Proxy
      ✓ balanceOf(): gets the balance of the account (92ms)
      ✓ totalSupply(): gets the total supply (51ms)
      ✓ name(): returns the token's name
      ✓ symbol(): returns the token's symbol
      ✓ decimal(): returns the number of decimal digits used
      ✓ allowance(): returns an account's spending allowance for another account's balance
      ✓ approve(): approves an account to spend the specified amount
      ✓ transferFrom(): successfully transfers from an account which is it approved to transfer from (90ms)
      ✓ transfer(): increases the recipient's balance by the correct amount
      ✓ transfer(): reverts if amount exceeds sender's balance
      ✓ transfer(): transferring to a blacklisted address reverts (213ms)
      ✓ increaseAllowance(): increases an account's allowance by the correct amount (39ms)
      ✓ transfer(): transferring to a blacklisted address reverts (112ms)
      ✓ decreaseAllowance(): decreases allowance by the expected amount
      ✓ decreaseAllowance(): fails trying to decrease more than previously allowed (49ms)

  Contract: All Mosaic functions with onlyOwner modifier
    TroveManager
      ✓ setAddresses(): reverts when called by non-owner, with wrong addresses, or twice (857ms)
    BorrowerOperations
      ✓ setAddresses(): reverts when called by non-owner, with wrong addresses, or twice (765ms)
    DefaultPool
      ✓ setAddresses(): reverts when called by non-owner, with wrong addresses, or twice (154ms)
    StabilityPool
      ✓ setAddresses(): reverts when called by non-owner, with wrong addresses, or twice (441ms)
    ActivePool
      ✓ setAddresses(): reverts when called by non-owner, with wrong addresses, or twice (468ms)
    SortedTroves
      ✓ setParams(): reverts when called by non-owner, with wrong addresses, or twice (157ms)
    CommunityIssuance
      ✓ setAddresses(): reverts when called by non-owner, with wrong addresses, or twice (136ms)
    MSICStaking
      ✓ setAddresses(): reverts when called by non-owner, with wrong addresses, or twice (261ms)
    LockupContractFactory
      ✓ setMSICAddress(): reverts when called by non-owner, with wrong address, or twice (216ms)

  Contract: StabilityPool
    ✓ getETH(): gets the recorded REEF balance
    ✓ getTotalMoUSDDeposits(): gets the recorded MoUSD balance

  Contract: ActivePool
    ✓ getETH(): gets the recorded REEF balance
    ✓ getMoUSDDebt(): gets the recorded MoUSD balance
    ✓ increaseMoUSD(): increases the recorded MoUSD balance by the correct amount
    ✓ decreaseMoUSD(): decreases the recorded MoUSD balance by the correct amount
    ✓ sendETH(): decreases the recorded REEF balance by the correct amount

  Contract: DefaultPool
    ✓ getETH(): gets the recorded MoUSD balance
    ✓ getMoUSDDebt(): gets the recorded MoUSD balance
    ✓ increaseMoUSD(): increases the recorded MoUSD balance by the correct amount
    ✓ decreaseMoUSD(): decreases the recorded MoUSD balance by the correct amount (57ms)
    ✓ sendETHToActivePool(): decreases the recorded REEF balance by the correct amount (50ms)

  Contract: PriceFeed
    ✓ C1 Chainlink working: fetchPrice should return the correct price, taking into account the number of decimal digits on the aggregator (286ms)
    ✓ C1 Chainlink breaks, Tellor working: fetchPrice should return the correct Tellor price, taking into account Tellor's 6-digit granularity (2595ms)
    ✓ C1 chainlinkWorking: Chainlink broken by zero latest roundId, Tellor working: switch to usingChainlinkTellorUntrusted (87ms)
    ✓ C1 chainlinkWorking: Chainlink broken by zero latest roundId, Tellor working: use Tellor price (93ms)
    ✓ C1 chainlinkWorking: Chainlink broken by zero timestamp, Tellor working, switch to usingChainlinkTellorUntrusted (97ms)
    ✓ C1 chainlinkWorking:  Chainlink broken by zero timestamp, Tellor working, return Tellor price (97ms)
    ✓ C1 chainlinkWorking: Chainlink broken by future timestamp, Tellor working, switch to usingChainlinkTellorUntrusted (94ms)
    ✓ C1 chainlinkWorking: Chainlink broken by future timestamp, Tellor working, return Tellor price (99ms)
    ✓ C1 chainlinkWorking: Chainlink broken by negative price, Tellor working,  switch to usingChainlinkTellorUntrusted (85ms)
    ✓ C1 chainlinkWorking: Chainlink broken by negative price, Tellor working, return Tellor price (82ms)
    ✓ C1 chainlinkWorking: Chainlink broken - decimals call reverted, Tellor working, switch to usingChainlinkTellorUntrusted (117ms)
    ✓ C1 chainlinkWorking: Chainlink broken - decimals call reverted, Tellor working, return Tellor price (99ms)
    ✓ C1 chainlinkWorking: Chainlink broken - latest round call reverted, Tellor working, switch to usingChainlinkTellorUntrusted (92ms)
    ✓ C1 chainlinkWorking: latest round call reverted, Tellor working, return the Tellor price (100ms)
    ✓ C1 chainlinkWorking: previous round call reverted, Tellor working, switch to usingChainlinkTellorUntrusted (101ms)
    ✓ C1 chainlinkWorking: previous round call reverted, Tellor working, return Tellor Price (102ms)
    ✓ C1 chainlinkWorking: Chainlink frozen, Tellor working: switch to usingTellorChainlinkFrozen (112ms)
    ✓ C1 chainlinkWorking: Chainlink frozen, Tellor working: return Tellor price (123ms)
    ✓ C1 chainlinkWorking: Chainlink frozen, Tellor frozen: switch to usingTellorChainlinkFrozen (119ms)
    ✓ C1 chainlinkWorking: Chainlink frozen, Tellor frozen: return last good price (127ms)
    ✓ C1 chainlinkWorking: Chainlink times out, Tellor broken by 0 price: switch to usingChainlinkTellorUntrusted (320ms)
    ✓ C1 chainlinkWorking: Chainlink times out, Tellor broken by 0 price: return last good price (146ms)
    ✓ C1 chainlinkWorking: Chainlink is out of date by <3hrs: remain chainlinkWorking (92ms)
    ✓ C1 chainlinkWorking: Chainlink is out of date by <3hrs: return Chainklink price (132ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50%, switch to usingChainlinkTellorUntrusted (117ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50%, return the Tellor price (132ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of 50%, remain chainlinkWorking (83ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of 50%, return the Chainlink price (376ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of <50%, remain chainlinkWorking (89ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of <50%, return Chainlink price (99ms)
    ✓ C1 chainlinkWorking: Chainlink price increase of >100%, switch to usingChainlinkTellorUntrusted (473ms)
    ✓ C1 chainlinkWorking: Chainlink price increase of >100%, return Tellor price (117ms)
    ✓ C1 chainlinkWorking: Chainlink price increase of 100%, remain chainlinkWorking (82ms)
    ✓ C1 chainlinkWorking: Chainlink price increase of 100%, return Chainlink price (350ms)
    ✓ C1 chainlinkWorking: Chainlink price increase of <100%, remain chainlinkWorking (136ms)
    ✓ C1 chainlinkWorking: Chainlink price increase of <100%,  return Chainlink price (87ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor price matches: remain chainlinkWorking (154ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor price matches: return Chainlink price (135ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor price within 5% of Chainlink: remain chainlinkWorking (109ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor price within 5% of Chainlink: return Chainlink price (101ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor live but not within 5% of Chainlink: switch to usingChainlinkTellorUntrusted (116ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor live but not within 5% of Chainlink: return Tellor price (276ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor frozen: switch to usingChainlinkTellorUntrusted (145ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor frozen: return last good price (2730ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor is broken by 0 price: switch to bothOracleSuspect (68ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor is broken by 0 price: return last good price (451ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor is broken by 0 timestamp: switch to bothOracleSuspect (121ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor is broken by 0 timestamp: return last good price (87ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor is broken by future timestamp: Pricefeed switches to bothOracleSuspect (81ms)
    ✓ C1 chainlinkWorking: Chainlink price drop of >50% and Tellor is broken by future timestamp: return last good price (119ms)
    ✓ C1 chainlinkWorking: Chainlink is working and Tellor is working - remain on chainlinkWorking (77ms)
    ✓ C1 chainlinkWorking: Chainlink is working and Tellor is working - return Chainlink price (168ms)
    ✓ C1 chainlinkWorking: Chainlink is working and Tellor freezes - remain on chainlinkWorking (469ms)
    ✓ C1 chainlinkWorking: Chainlink is working and Tellor freezes - return Chainlink price (167ms)
    ✓ C1 chainlinkWorking: Chainlink is working and Tellor breaks: switch to usingChainlinkTellorUntrusted (206ms)
    ✓ C1 chainlinkWorking: Chainlink is working and Tellor breaks: return Chainlink price (105ms)
    ✓ C2 usingTellorChainlinkUntrusted: Tellor breaks by zero price: switch to bothOraclesSuspect (202ms)
    ✓ C2 usingTellorChainlinkUntrusted: Tellor breaks by zero price: return last good price (107ms)
    ✓ C2 usingTellorChainlinkUntrusted: Tellor breaks by call reverted: switch to bothOraclesSuspect (296ms)
    ✓ C2 usingTellorChainlinkUntrusted: Tellor breaks by call reverted: return last good price (112ms)
    ✓ C2 usingTellorChainlinkUntrusted: Tellor breaks by zero timestamp: switch to bothOraclesSuspect (2577ms)
    ✓ C2 usingTellorChainlinkUntrusted: Tellor breaks by zero timestamp: return last good price (82ms)
    ✓ C2 usingTellorChainlinkUntrusted: Tellor freezes - remain usingChainlinkTellorUntrusted (534ms)
    ✓ C2 usingTellorChainlinkUntrusted: Tellor freezes - return last good price (123ms)
    ✓ C2 usingTellorChainlinkUntrusted: both Tellor and Chainlink are live and <= 5% price difference - switch to chainlinkWorking (68ms)
    ✓ C2 usingTellorChainlinkUntrusted: both Tellor and Chainlink are live and <= 5% price difference - return Chainlink price (65ms)
    ✓ C2 usingTellorChainlinkUntrusted: both Tellor and Chainlink are live and > 5% price difference - remain usingChainlinkTellorUntrusted (86ms)
    ✓ C2 usingTellorChainlinkUntrusted: both Tellor and Chainlink are live and > 5% price difference - return Tellor price (569ms)
    ✓ C3 bothOraclesUntrusted: both Tellor and Chainlink are live and > 5% price difference remain bothOraclesSuspect (56ms)
    ✓ C3 bothOraclesUntrusted: both Tellor and Chainlink are live and > 5% price difference, return last good price (82ms)
    ✓ C3 bothOraclesUntrusted: both Tellor and Chainlink are live and <= 5% price difference, switch to chainlinkWorking (72ms)
    ✓ C3 bothOraclesUntrusted: both Tellor and Chainlink are live and <= 5% price difference, return Chainlink price (84ms)
    ✓ C4 usingTellorChainlinkFrozen: when both Chainlink and Tellor break, switch to bothOraclesSuspect (459ms)
    ✓ C4 usingTellorChainlinkFrozen: when both Chainlink and Tellor break, return last good price (112ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink breaks and Tellor freezes, switch to usingChainlinkTellorUntrusted (112ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink breaks and Tellor freezes, return last good price (99ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink breaks and Tellor live, switch to usingChainlinkTellorUntrusted (106ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink breaks and Tellor live, return Tellor price (102ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink is live and Tellor is live with <5% price difference, switch back to chainlinkWorking (113ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink is live and Tellor is live with <5% price difference, return Chainlink current price (138ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink is live and Tellor is live with >5% price difference, switch back to usingChainlinkTellorUntrusted (2467ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink is live and Tellor is live with >5% price difference, return Chainlink current price (85ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink is live and Tellor is live with similar price, switch back to chainlinkWorking (537ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink is live and Tellor is live with similar price, return Chainlink current price (82ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink is live and Tellor breaks, switch to usingChainlinkTellorUntrusted (187ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink is live and Tellor breaks, return Chainlink current price (81ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink still frozen and Tellor breaks, switch to usingChainlinkTellorUntrusted (176ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink still frozen and Tellor broken, return last good price (213ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink still frozen and Tellor live, remain usingTellorChainlinkFrozen (140ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink still frozen and Tellor live, return Tellor price (236ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink still frozen and Tellor freezes, remain usingTellorChainlinkFrozen (107ms)
    ✓ C4 usingTellorChainlinkFrozen: when Chainlink still frozen and Tellor freezes, return last good price (261ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink is live and Tellor price >5% - no status change (109ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink is live and Tellor price >5% - return Chainlink price (96ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink is live and Tellor price within <5%, switch to chainlinkWorking (171ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink is live, Tellor price not within 5%, return Chainlink price (111ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink is live, <50% price deviation from previous, Tellor price not within 5%, remain on usingChainlinkTellorUntrusted (161ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink is live, <50% price deviation from previous, Tellor price not within 5%, return Chainlink price (223ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink is live, >50% price deviation from previous, Tellor price not within 5%, remain on usingChainlinkTellorUntrusted (124ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink is live, >50% price deviation from previous,  Tellor price not within 5%, return Chainlink price (182ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink is live, <50% price deviation from previous, and Tellor is frozen, remain on usingChainlinkTellorUntrusted (552ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink is live, <50% price deviation from previous, Tellor is frozen, return Chainlink price (103ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink is live, >50% price deviation from previous, Tellor is frozen, remain on usingChainlinkTellorUntrusted (121ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink is live, >50% price deviation from previous, Tellor is frozen, return Chainlink price (105ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink frozen, remain on usingChainlinkTellorUntrusted (107ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink frozen, return last good price (531ms)
    ✓ C5 usingChainlinkTellorUntrusted: when Chainlink breaks too, switch to bothOraclesSuspect (87ms)
    ✓ C5 usingChainlinkTellorUntrusted: Chainlink breaks too, return last good price (99ms)
    PriceFeed internal testing contract
      ✓ fetchPrice before setPrice should return the default price
      ✓ should be able to fetchPrice after setPrice, output of former matching input of latter
    Mainnet PriceFeed setup
      ✓ fetchPrice should fail on contract with no chainlink address set
      ✓ fetchPrice should fail on contract with no tellor address set
      ✓ setAddresses should fail whe called by nonOwner
      ✓ setAddresses should fail after address has already been set (42ms)

  Contract: BorrowerWrappers
    ✓ proxy owner can recover REEF (85ms)
    ✓ non proxy owner cannot recover REEF
    ✓ claimCollateralAndOpenTrove(): reverts if nothing to claim (388ms)
    ✓ claimCollateralAndOpenTrove(): without sending any value (1227ms)
    ✓ claimCollateralAndOpenTrove(): sending value in the transaction (3969ms)
    ✓ claimSPRewardsAndRecycle(): only owner can call it (598ms)
    ✓ claimSPRewardsAndRecycle(): (1272ms)
    ✓ claimStakingGainsAndRecycle(): only owner can call it (1384ms)
    ✓ claimStakingGainsAndRecycle(): reverts if user has no trove (1253ms)
    ✓ claimStakingGainsAndRecycle(): with only REEF gain (1595ms)
    ✓ claimStakingGainsAndRecycle(): with only MoUSD gain (821ms)
    ✓ claimStakingGainsAndRecycle(): with both REEF and MoUSD gains (1593ms)

  Contract: SortedTroves
    SortedTroves
      ✓ contains(): returns true for addresses that have opened troves (552ms)
      ✓ contains(): returns false for addresses that have not opened troves (518ms)
      ✓ contains(): returns false for addresses that opened and then closed a trove (1009ms)
      ✓ contains(): returns true for addresses that opened, closed and then re-opened a trove (1399ms)
      ✓ contains(): returns false when there are no troves in the system
      ✓ contains(): true when list size is 1 and the trove the only one in system (208ms)
      ✓ contains(): false when list size is 1 and trove is not in the system (158ms)
      ✓ getMaxSize(): Returns the maximum list size
      ✓ Finds the correct insert position given two addresses that loosely bound the correct position (1135ms)
      - stays ordered after troves with 'infinite' ICR receive a redistribution
    SortedTroves with mock dependencies
      when params are wrongly set
        ✓ setParams(): reverts if size is zero
      when params are properly set
        ✓ insert(): fails if list is full (131ms)
        ✓ insert(): fails if list already contains the node (54ms)
        ✓ insert(): fails if id is zero
        ✓ insert(): fails if NICR is zero
        ✓ remove(): fails if id is not in the list
        ✓ reInsert(): fails if list doesn’t contain the node
        ✓ reInsert(): fails if new NICR is zero (43ms)
        ✓ findInsertPosition(): No prevId for hint - ascend list starting from nextId, result is after the tail

  Contract: StabilityPool - MSIC Rewards
    MSIC Rewards
totalMSICIssued_1: 30370113195977152000000
totalMSICIssued_2: 30370113195977152000000
      ✓ liquidation < 1 minute after a deposit does not change totalMSICIssued (743ms)
      ✓ withdrawFromSP(): reward term G does not update when no MSIC is issued (634ms)