Skip to content

Commit

Permalink
Merge pull request #1361 from morpho-dao/recover/collateral-check
Browse files Browse the repository at this point in the history
Recover collateral check
  • Loading branch information
MerlinEgalite authored Oct 26, 2022
2 parents 4f35c1a + 380a301 commit 7da1a5c
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 2 deletions.
16 changes: 16 additions & 0 deletions contracts/aave-v2/MorphoUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import "./interfaces/aave/IPriceOracleGetter.sol";
import "./interfaces/aave/IAToken.sol";

import "./libraries/aave/ReserveConfiguration.sol";
import "./libraries/aave/UserConfiguration.sol";

import "@morpho-dao/morpho-utils/DelegateCall.sol";
import "@morpho-dao/morpho-utils/math/PercentageMath.sol";
import "@morpho-dao/morpho-utils/math/WadRayMath.sol";
Expand All @@ -18,6 +20,7 @@ import "./MorphoStorage.sol";
/// @notice Modifiers, getters and other util functions for Morpho.
abstract contract MorphoUtils is MorphoStorage {
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using UserConfiguration for DataTypes.UserConfigurationMap;
using HeapOrdering for HeapOrdering.HeapArray;
using PercentageMath for uint256;
using DelegateCall for address;
Expand Down Expand Up @@ -274,6 +277,11 @@ abstract contract MorphoUtils is MorphoStorage {
IPriceOracleGetter oracle = IPriceOracleGetter(addressesProvider.getPriceOracle());
Types.AssetLiquidityData memory assetData;
Types.LiquidityStackVars memory vars;

DataTypes.UserConfigurationMap memory morphoPoolConfig = pool.getUserConfiguration(
address(this)
);

vars.poolTokensLength = marketsCreated.length;
vars.userMarkets = userMarkets[_user];

Expand All @@ -296,6 +304,14 @@ abstract contract MorphoUtils is MorphoStorage {
assetData.tokenUnit = 10**assetData.decimals;
}

// LTV and liquidation threshold should be zero if Morpho has not enabled this asset as collateral.
if (
!morphoPoolConfig.isUsingAsCollateral(pool.getReserveData(vars.underlyingToken).id)
) {
assetData.ltv = 0;
assetData.liquidationThreshold = 0;
}

if (_isBorrowing(vars.userMarkets, vars.borrowMask)) {
values.debt += _debtValue(
vars.poolToken,
Expand Down
16 changes: 16 additions & 0 deletions contracts/aave-v2/libraries/aave/UserConfiguration.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GNU AGPLv3
pragma solidity ^0.8.0;

import {DataTypes} from "./DataTypes.sol";

library UserConfiguration {
function isUsingAsCollateral(DataTypes.UserConfigurationMap memory self, uint256 reserveIndex)
internal
pure
returns (bool)
{
unchecked {
return (self.data >> ((reserveIndex << 1) + 1)) & 1 != 0;
}
}
}
4 changes: 2 additions & 2 deletions contracts/aave-v3/MorphoUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ abstract contract MorphoUtils is MorphoStorage {
Types.AssetLiquidityData memory assetData;
Types.LiquidityStackVars memory vars;

DataTypes.UserConfigurationMap memory morphoUserConfig = pool.getUserConfiguration(
DataTypes.UserConfigurationMap memory morphoPoolConfig = pool.getUserConfiguration(
address(this)
);
vars.poolTokensLength = marketsCreated.length;
Expand All @@ -279,7 +279,7 @@ abstract contract MorphoUtils is MorphoStorage {
.getParams();

// LTV should be zero if Morpho has not enabled this asset as collateral
if (!morphoUserConfig.isUsingAsCollateral(pool.getReserveData(vars.underlyingToken).id))
if (!morphoPoolConfig.isUsingAsCollateral(pool.getReserveData(vars.underlyingToken).id))
assetData.ltv = 0;

// If a LTV has been reduced to 0 on Aave v3, the other assets of the collateral are frozen.
Expand Down
17 changes: 17 additions & 0 deletions test-foundry/aave-v2/TestBorrow.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,21 @@ contract TestBorrow is TestSetup {
hevm.expectRevert(EntryPositionsManager.UnauthorisedBorrow.selector);
borrower1.borrow(aDai, (amount * ltv) / 10_000 + 1e9);
}

function testShouldNotBorrowWithDisabledCollateral() public {
uint256 amount = 100 ether;

borrower1.approve(dai, type(uint256).max);
borrower1.supply(aDai, amount * 10);

// Give Morpho a position on the pool to be able to unset the DAI asset as collateral.
// Without this position on the pool, it's not possible to do so.
supplier1.approve(usdc, to6Decimals(amount));
supplier1.supply(aUsdc, to6Decimals(amount));

morpho.setAssetAsCollateral(aDai, false);

hevm.expectRevert(EntryPositionsManager.UnauthorisedBorrow.selector);
borrower1.borrow(aUsdc, to6Decimals(amount));
}
}
17 changes: 17 additions & 0 deletions test-foundry/aave-v3/TestBorrow.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -238,4 +238,21 @@ contract TestBorrow is TestSetup {
hevm.expectRevert(EntryPositionsManager.UnauthorisedBorrow.selector);
borrower1.borrow(aUsdc, amount);
}

function testShouldNotBorrowWithDisabledCollateral() public {
uint256 amount = 100 ether;

borrower1.approve(dai, type(uint256).max);
borrower1.supply(aDai, amount * 10);

// Give Morpho a position on the pool to be able to unset the DAI asset as collateral.
// Without this position on the pool, it's not possible to do so.
supplier1.approve(usdc, to6Decimals(amount));
supplier1.supply(aUsdc, to6Decimals(amount));

morpho.setAssetAsCollateral(aDai, false);

hevm.expectRevert(EntryPositionsManager.UnauthorisedBorrow.selector);
borrower1.borrow(aUsdc, to6Decimals(amount));
}
}

0 comments on commit 7da1a5c

Please sign in to comment.