Users are unable close or add to their Lyra vault positions when price is stale or circuit breaker is tripped
Users are unable close or add to their Lyra vault positions when price is stale or circuit breaker is tripped. This is problematic for a few reasons. First is that the circuit breaker can be tripped indefinitely which means their collateral could be frozen forever and they will be accumulating interest the entire time they are frozen. The second is that since they can't add any additional collateral to their loan, the loan may end up being underwater by the time the price is no longer stale or circuit breaker is no longer tripped. They may have wanted to add more assets and now they are liquidated, which is unfair as users who are liquidated are effectively forced to pay a fee to the liquidator.\\n```\\nfunction _checkIfCollateralIsActive(bytes32 _currencyKey) internal view override {\\n        \\n         //Lyra LP tokens use their associated LiquidityPool to check if they're active\\n         ILiquidityPoolAvalon LiquidityPool = ILiquidityPoolAvalon(collateralBook.liquidityPoolOf(_currencyKey));\\n         bool isStale;\\n         uint circuitBreakerExpiry;\\n         //ignore first output as this is the token price and not needed yet.\\n         (, isStale, circuitBreakerExpiry) = LiquidityPool.getTokenPriceWithCheck();\\n         require( !(isStale), "Global Cache Stale, can't trade");\\n         require(circuitBreakerExpiry < block.timestamp, "Lyra Circuit Breakers active, can't trade");\\n}\\n```\\n\\nThe above lines are run every time a user a user tries to interact with the vault. Currently this is overly restrictive and can lead to a lot of undesired situations, as explained in the summary.
The contract is frozen when price is stale or circuit breaker is tripped to prevent price manipulation. While it should restrict a majority of actions there are a two that don't need any price validation. If a user wishes to close out their entire loan then there is no need for price validation because the user has no more debt and therefore doesn't need to maintain any level of collateralization. The other situation is if a user adds collateral to their vault and doesn't take out any more loans. In this scenario, the collateralization can only increase, which means that price validation is not necessary.\\nI recommend the following changes to closeLoan:\\n```\\n-   _checkIfCollateralIsActive(currencyKey);\\n    uint256 isoUSDdebt = (isoUSDLoanAndInterest[_collateralAddress][msg.sender] * virtualPrice) / LOAN_SCALE;\\n    require( isoUSDdebt >= _USDToVault, "Trying to return more isoUSD than borrowed!");\\n    uint256 outstandingisoUSD = isoUSDdebt - _USDToVault;\\n    if(outstandingisoUSD >= TENTH_OF_CENT){ //ignore leftover debts less than $0.001\\n+       //only need to check collateral value if user has remaining debt\\n+       _checkIfCollateralIsActive(currencyKey);\\n        uint256 collateralLeft = collateralPosted[_collateralAddress][msg.sender] - _collateralToUser;\\n        uint256 colInUSD = priceCollateralToUSD(currencyKey, collateralLeft); \\n        uint256 borrowMargin = (outstandingisoUSD * minOpeningMargin) / LOAN_SCALE;\\n        require(colInUSD > borrowMargin , "Remaining debt fails to meet minimum margin!");\\n    }\\n```\\n\\nI recommend removing liquidation threshold check from increaseCollateralAmount:\\n```\\n    //debatable check begins here \\n-   uint256 totalCollat = collateralPosted[_collateralAddress][msg.sender] + _colAmount;\\n-   uint256 colInUSD = priceCollateralToUSD(currencyKey, totalCollat);\\n-   uint256 USDborrowed = (isoUSDLoanAndInterest[_collateralAddress][msg.sender] * virtualPrice) / LOAN_SCALE;\\n-   uint256 borrowMargin = (USDborrowed * liquidatableMargin) / LOAN_SCALE;\\n-   require(colInUSD >= borrowMargin, "Liquidation margin not met!");\\n    //debatable check ends here\\n```\\n
Frozen assets, unfair interest accumulation and unfair liquidations
```\\nfunction _checkIfCollateralIsActive(bytes32 _currencyKey) internal view override {\\n        \\n         //Lyra LP tokens use their associated LiquidityPool to check if they're active\\n         ILiquidityPoolAvalon LiquidityPool = ILiquidityPoolAvalon(collateralBook.liquidityPoolOf(_currencyKey));\\n         bool isStale;\\n         uint circuitBreakerExpiry;\\n         //ignore first output as this is the token price and not needed yet.\\n         (, isStale, circuitBreakerExpiry) = LiquidityPool.getTokenPriceWithCheck();\\n         require( !(isStale), "Global Cache Stale, can't trade");\\n         require(circuitBreakerExpiry < block.timestamp, "Lyra Circuit Breakers active, can't trade");\\n}\\n```\\n