hifi-finance / hifi

Monorepo implementing the Hifi fixed-rate, fixed-term lending protocol
https://app.hifi.finance
Other
105 stars 15 forks source link

feat(flash-swap): support liquidating vaults with underlying as collateral #64

Closed scorpion9979 closed 2 years ago

scorpion9979 commented 2 years ago

Regarding liquidating USDC collateral, the following modifications needed to be applied to the flash-swap contract:

  1. The bot is not able to access a USDC-USDC trading pair, and so for this special case we are assuming the use of any pair that has USDC on one side. In real life, the pair would preferably be the one with the largest liquidity out of all pairs containing USDC on one side.
  2. Since we're only going to be using one side of the trading pair, we need to repay the borrowed USDC in USDC + 0.3% Uniswap v2 fee. This required modifying the getRepayCollateralAmount(...) function in flash-swap to enable different calculation for this special case.
  3. We also needed to do something about the msg.sender verification in flash-swap, as it previously required the msg sender address to be equal to the pair address of underlying and collateral computed using pairFor(...). Since it's not possible to have a USDC-USDC pair, we needed to constrain this check to the case where the underlying token is not the same as the collateral to be liquidated.
  4. The liquidated collateral is not going to be enough to repay the 0.3% Uniswap fee. A modification was needed to enable the liquidation bot wallet to repay the fee from its own balance if necessary. The flash swap contract expects there would be no profit from liquidations, as the USDC collateralization requirement is 100%.
PaulRBerg commented 2 years ago

I refactored pretty much everything. For a detailed log, see the commit messages. Here's the high level:

You can add your review @scorpion9979 and then I will merge the PR.

PaulRBerg commented 2 years ago

After another review, I noticed three other issues:

  1. Many tests written for UnderlyingFlashUniswapV2 are pointless. All the tests whose beforeEach block manipulate the WBTC price (probably copy-pasted from the other contract's test), but in this case it is not possible to have a liquidity shortfall when the borrow is backed by the underlying itself, and there is no swap made, so the UniswapV2Pair contract does NOT give any price.
  2. The tests for UnderlyingFlashUniswapV2 should have accounted for the time-contingent nature of underlying-backed vaults.
  3. The implementation is incomplete: the "else" logical branch of the if block below should have been handled:
if (vars.repayUnderlyingAmount > vars.seizedUnderlyingAmount)

Any surplus of underlying should be relayed to the caller, just like we're doing in CollateralFlashUniswapV2.

Already started working on fixes.

PaulRBerg commented 2 years ago

This was a hairy refactor ... I made progress with the latest commit, but the following test cases are still not written:

I'll handle them tomorrow.