From a98956f8b29212b2566f903239c20741e65d44fd Mon Sep 17 00:00:00 2001 From: The3D Date: Mon, 5 Jul 2021 19:54:59 +0200 Subject: [PATCH 1/4] fix: remove exposure cap specific code and configuration --- .../deployments/ATokensAndRatesHelper.sol | 4 +- .../interfaces/ILendingPoolConfigurator.sol | 18 +------ contracts/misc/AaveProtocolDataProvider.sol | 5 +- contracts/misc/UiPoolDataProvider.sol | 2 +- .../misc/interfaces/IUiPoolDataProvider.sol | 1 - .../protocol/lendingpool/LendingPool.sol | 9 ++-- .../lendingpool/LendingPoolConfigurator.sol | 19 +------ .../configuration/ReserveConfiguration.sol | 51 +------------------ .../protocol/libraries/helpers/Errors.sol | 2 +- .../protocol/libraries/logic/GenericLogic.sol | 46 ++++------------- .../libraries/logic/ValidationLogic.sol | 30 ++++------- 11 files changed, 30 insertions(+), 157 deletions(-) diff --git a/contracts/deployments/ATokensAndRatesHelper.sol b/contracts/deployments/ATokensAndRatesHelper.sol index 5d77bb44..15a5e81a 100644 --- a/contracts/deployments/ATokensAndRatesHelper.sol +++ b/contracts/deployments/ATokensAndRatesHelper.sol @@ -33,7 +33,6 @@ contract ATokensAndRatesHelper is Ownable { uint256 reserveFactor; uint256 borrowCap; uint256 supplyCap; - uint256 exposureCap; bool stableBorrowingEnabled; bool borrowingEnabled; } @@ -74,8 +73,7 @@ contract ATokensAndRatesHelper is Ownable { inputParams[i].asset, inputParams[i].baseLTV, inputParams[i].liquidationThreshold, - inputParams[i].liquidationBonus, - inputParams[i].exposureCap + inputParams[i].liquidationBonus ); if (inputParams[i].borrowingEnabled) { diff --git a/contracts/interfaces/ILendingPoolConfigurator.sol b/contracts/interfaces/ILendingPoolConfigurator.sol index 092a8d6a..e7f855a1 100644 --- a/contracts/interfaces/ILendingPoolConfigurator.sol +++ b/contracts/interfaces/ILendingPoolConfigurator.sol @@ -159,13 +159,6 @@ interface ILendingPoolConfigurator { **/ event SupplyCapChanged(address indexed asset, uint256 supplyCap); - /** - * @dev Emitted when the exposure cap of a reserve is updated - * @param asset The address of the underlying asset of the reserve - * @param exposureCap The new exposure cap - **/ - event ExposureCapChanged(address indexed asset, uint256 exposureCap); - /** * @dev Emitted when the reserve decimals are updated * @param asset The address of the underlying asset of the reserve @@ -301,15 +294,13 @@ interface ILendingPoolConfigurator { * @param ltv The loan to value of the asset when used as collateral * @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized * @param liquidationBonus The bonus liquidators receive to liquidate this asset. The values is always above 100%. A value of 105% - * @param exposureCap The exposure cap for the collateral reserve. If cap is reached, effective LTV = 0 * means the liquidator will receive a 5% bonus **/ function configureReserveAsCollateral( address asset, uint256 ltv, uint256 liquidationThreshold, - uint256 liquidationBonus, - uint256 exposureCap + uint256 liquidationBonus ) external; /** @@ -392,13 +383,6 @@ interface ILendingPoolConfigurator { **/ function setSupplyCap(address asset, uint256 supplyCap) external; - /** - * @dev Updates the exposure cap of a reserve - * @param asset The address of the underlying asset of the reserve - * @param exposureCap The new exposure of the reserve - **/ - function setExposureCap(address asset, uint256 exposureCap) external; - /** * @dev Registers a new admin with rights on risk related configurations * @param admin The address of the admin to register diff --git a/contracts/misc/AaveProtocolDataProvider.sol b/contracts/misc/AaveProtocolDataProvider.sol index ea22b29e..5afbac05 100644 --- a/contracts/misc/AaveProtocolDataProvider.sol +++ b/contracts/misc/AaveProtocolDataProvider.sol @@ -98,11 +98,10 @@ contract AaveProtocolDataProvider { view returns ( uint256 borrowCap, - uint256 supplyCap, - uint256 exposureCap + uint256 supplyCap ) { - (borrowCap, supplyCap, exposureCap) = ILendingPool(ADDRESSES_PROVIDER.getLendingPool()) + (borrowCap, supplyCap) = ILendingPool(ADDRESSES_PROVIDER.getLendingPool()) .getConfiguration(asset) .getCapsMemory(); } diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 8c05686c..8c5621e7 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -114,7 +114,7 @@ contract UiPoolDataProvider is IUiPoolDataProvider { reserveData.decimals, reserveData.reserveFactor ) = baseData.configuration.getParamsMemory(); - (reserveData.borrowCap, reserveData.supplyCap, reserveData.exposureCap) = baseData + (reserveData.borrowCap, reserveData.supplyCap) = baseData .configuration .getCapsMemory(); ( diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index fdfd6895..ac7d344a 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -17,7 +17,6 @@ interface IUiPoolDataProvider { uint256 reserveFactor; uint256 borrowCap; uint256 supplyCap; - uint256 exposureCap; bool usageAsCollateralEnabled; bool borrowingEnabled; bool stableBorrowRateEnabled; diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 4bfe23f9..661dff93 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -278,9 +278,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage if (useAsCollateral) { emit ReserveUsedAsCollateralEnabled(asset, msg.sender); } else { - ValidationLogic.validateHFAndExposureCap( + ValidationLogic.validateHFAndLtv( asset, - userBalance, msg.sender, _reserves, _usersConfig[msg.sender], @@ -620,9 +619,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage if (fromConfig.isUsingAsCollateral(reserveId)) { if (fromConfig.isBorrowingAny()) { - ValidationLogic.validateHFAndExposureCap( + ValidationLogic.validateHFAndLtv( asset, - amount, from, _reserves, _usersConfig[from], @@ -864,9 +862,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage if (userConfig.isUsingAsCollateral(reserve.id)) { if (userConfig.isBorrowingAny()) { - ValidationLogic.validateHFAndExposureCap( + ValidationLogic.validateHFAndLtv( asset, - 0, msg.sender, _reserves, userConfig, diff --git a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol index 4ecc8b2d..79367945 100644 --- a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol @@ -296,8 +296,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur address asset, uint256 ltv, uint256 liquidationThreshold, - uint256 liquidationBonus, - uint256 exposureCap + uint256 liquidationBonus ) external override onlyRiskOrPoolAdmins { DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); @@ -331,7 +330,6 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur currentConfig.setLtv(ltv); currentConfig.setLiquidationThreshold(liquidationThreshold); currentConfig.setLiquidationBonus(liquidationBonus); - currentConfig.setExposureCap(exposureCap); _pool.setConfiguration(asset, currentConfig.data); @@ -458,21 +456,6 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur emit SupplyCapChanged(asset, supplyCap); } - ///@inheritdoc ILendingPoolConfigurator - function setExposureCap(address asset, uint256 exposureCap) - external - override - onlyRiskOrPoolAdmins - { - DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); - - currentConfig.setExposureCap(exposureCap); - - _pool.setConfiguration(asset, currentConfig.data); - - emit ExposureCapChanged(asset, exposureCap); - } - ///@inheritdoc ILendingPoolConfigurator function setReserveInterestRateStrategyAddress(address asset, address rateStrategyAddress) external diff --git a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol index ba2aa0c4..b285b9ef 100644 --- a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol @@ -22,7 +22,6 @@ library ReserveConfiguration { uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore uint256 constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore uint256 constant SUPPLY_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore - uint256 constant EXPOSURE_CAP_MASK = 0xFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore /// @dev For the LTV, the start bit is 0 (up to 15), hence no bitshifting is needed uint256 constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16; @@ -37,7 +36,6 @@ library ReserveConfiguration { uint256 constant RESERVE_FACTOR_START_BIT_POSITION = 64; uint256 constant BORROW_CAP_START_BIT_POSITION = 80; uint256 constant SUPPLY_CAP_START_BIT_POSITION = 116; - uint256 constant EXPOSURE_CAP_START_BIT_POSITION = 152; uint256 constant MAX_VALID_LTV = 65535; uint256 constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535; @@ -46,7 +44,6 @@ library ReserveConfiguration { uint256 constant MAX_VALID_RESERVE_FACTOR = 65535; uint256 constant MAX_VALID_BORROW_CAP = 68719476735; uint256 constant MAX_VALID_SUPPLY_CAP = 68719476735; - uint256 constant MAX_VALID_EXPOSURE_CAP = 68719476735; /** * @dev Sets the Loan to Value of the reserve @@ -386,33 +383,6 @@ library ReserveConfiguration { return (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION; } - /** - * @dev Sets the exposure cap of the reserve - * @param self The reserve configuration - * @param exposureCap The exposure cap - **/ - function setExposureCap(DataTypes.ReserveConfigurationMap memory self, uint256 exposureCap) - internal - pure - { - require(exposureCap <= MAX_VALID_EXPOSURE_CAP, Errors.RC_INVALID_EXPOSURE_CAP); - - self.data = (self.data & EXPOSURE_CAP_MASK) | (exposureCap << EXPOSURE_CAP_START_BIT_POSITION); - } - - /** - * @dev Gets the exposure cap of the reserve - * @param self The reserve configuration - * @return The exposure cap - **/ - function getExposureCap(DataTypes.ReserveConfigurationMap storage self) - internal - view - returns (uint256) - { - return (self.data & ~EXPOSURE_CAP_MASK) >> EXPOSURE_CAP_START_BIT_POSITION; - } - /** * @dev Gets the configuration flags of the reserve * @param self The reserve configuration @@ -476,7 +446,6 @@ library ReserveConfiguration { internal view returns ( - uint256, uint256, uint256 ) @@ -485,8 +454,7 @@ library ReserveConfiguration { return ( (dataLocal & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION, - (dataLocal & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION, - (dataLocal & ~EXPOSURE_CAP_MASK) >> EXPOSURE_CAP_START_BIT_POSITION + (dataLocal & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION ); } @@ -524,15 +492,13 @@ library ReserveConfiguration { internal pure returns ( - uint256, uint256, uint256 ) { return ( (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION, - (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION, - (self.data & ~EXPOSURE_CAP_MASK) >> EXPOSURE_CAP_START_BIT_POSITION + (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION ); } @@ -586,17 +552,4 @@ library ReserveConfiguration { { return (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION; } - - /** - * @dev Gets the exposure cap of the reserve from a memory object - * @param self The reserve configuration - * @return The exposure cap - **/ - function getExposureCapMemory(DataTypes.ReserveConfigurationMap memory self) - internal - pure - returns (uint256) - { - return (self.data & ~EXPOSURE_CAP_MASK) >> EXPOSURE_CAP_START_BIT_POSITION; - } } diff --git a/contracts/protocol/libraries/helpers/Errors.sol b/contracts/protocol/libraries/helpers/Errors.sol index 53e966c3..b4c14221 100644 --- a/contracts/protocol/libraries/helpers/Errors.sol +++ b/contracts/protocol/libraries/helpers/Errors.sol @@ -114,7 +114,7 @@ library Errors { string public constant RL_VARIABLE_DEBT_SUPPLY_NOT_ZERO = '90'; string public constant LP_CALLER_NOT_EOA = '91'; string public constant RC_INVALID_EXPOSURE_CAP = '92'; - string public constant VL_COLLATERAL_EXPOSURE_CAP_EXCEEDED = '93'; + string public constant VL_LTV_VALIDATION_FAILED = '93'; string public constant VL_SAME_BLOCK_BORROW_REPAY = '94'; string public constant LPC_FLASHLOAN_PREMIUMS_MISMATCH = '95'; string public constant LPC_FLASHLOAN_PREMIUM_INVALID = '96'; diff --git a/contracts/protocol/libraries/logic/GenericLogic.sol b/contracts/protocol/libraries/logic/GenericLogic.sol index 66053b6e..1e6fa024 100644 --- a/contracts/protocol/libraries/logic/GenericLogic.sol +++ b/contracts/protocol/libraries/logic/GenericLogic.sol @@ -44,18 +44,11 @@ library GenericLogic { uint256 totalCollateralInETH; uint256 totalDebtInETH; uint256 avgLtv; - uint256 avgUncappedLtv; uint256 avgLiquidationThreshold; - uint256 reservesLength; uint256 normalizedIncome; uint256 normalizedDebt; - uint256 exposureCap; - uint256 aTokenSupply; - bool healthFactorBelowThreshold; address currentReserveAddress; - bool usageAsCollateralEnabled; - bool userUsesReserveAsCollateral; - bool exposureCapCrossed; + bool hasZeroLtvCollateral; } /** @@ -85,13 +78,13 @@ library GenericLogic { uint256, uint256, uint256, - uint256 + bool ) { CalculateUserAccountDataVars memory vars; if (userConfig.isEmpty()) { - return (0, 0, 0, 0, uint256(-1), 0); + return (0, 0, 0, 0, uint256(-1), false); } for (vars.i = 0; vars.i < reservesCount; vars.i++) { if (!userConfig.isUsingAsCollateralOrBorrowing(vars.i)) { @@ -107,38 +100,20 @@ library GenericLogic { (vars.ltv, vars.liquidationThreshold, , vars.decimals, ) = currentReserve .configuration .getParams(); - vars.exposureCap = currentReserve.configuration.getExposureCap(); vars.assetUnit = 10**vars.decimals; vars.assetPrice = IPriceOracleGetter(oracle).getAssetPrice(vars.currentReserveAddress); if (vars.liquidationThreshold != 0 && userConfig.isUsingAsCollateral(vars.i)) { vars.normalizedIncome = currentReserve.getNormalizedIncome(); - - if (vars.exposureCap != 0) { - (vars.userBalance, vars.aTokenSupply) = IScaledBalanceToken(currentReserve.aTokenAddress) - .getScaledUserBalanceAndSupply(user); - - vars.userBalance = vars.userBalance.rayMul(vars.normalizedIncome); - vars.aTokenSupply = vars.aTokenSupply.rayMul(vars.normalizedIncome); - } else { - vars.userBalance = IScaledBalanceToken(currentReserve.aTokenAddress).scaledBalanceOf( - user - ); - vars.userBalance = vars.userBalance.rayMul(vars.normalizedIncome); - vars.aTokenSupply = 0; - } + vars.userBalance = IScaledBalanceToken(currentReserve.aTokenAddress).scaledBalanceOf(user); + vars.userBalance = vars.userBalance.rayMul(vars.normalizedIncome); vars.userBalanceETH = vars.assetPrice.mul(vars.userBalance).div(vars.assetUnit); vars.totalCollateralInETH = vars.totalCollateralInETH.add(vars.userBalanceETH); - vars.exposureCapCrossed = - vars.exposureCap != 0 && - vars.aTokenSupply.div(10**vars.decimals) > vars.exposureCap; - vars.avgLtv = vars.avgLtv.add( - vars.exposureCapCrossed ? 0 : vars.userBalanceETH.mul(vars.ltv) - ); - vars.avgUncappedLtv = vars.avgUncappedLtv.add(vars.userBalanceETH.mul(vars.ltv)); + vars.avgLtv = vars.avgLtv.add(vars.userBalanceETH.mul(vars.ltv)); + vars.hasZeroLtvCollateral = vars.ltv == 0; vars.avgLiquidationThreshold = vars.avgLiquidationThreshold.add( vars.userBalanceETH.mul(vars.liquidationThreshold) ); @@ -160,9 +135,6 @@ library GenericLogic { } vars.avgLtv = vars.totalCollateralInETH > 0 ? vars.avgLtv.div(vars.totalCollateralInETH) : 0; - vars.avgUncappedLtv = vars.totalCollateralInETH > 0 - ? vars.avgUncappedLtv.div(vars.totalCollateralInETH) - : 0; vars.avgLiquidationThreshold = vars.totalCollateralInETH > 0 ? vars.avgLiquidationThreshold.div(vars.totalCollateralInETH) : 0; @@ -178,7 +150,7 @@ library GenericLogic { vars.avgLtv, vars.avgLiquidationThreshold, vars.healthFactor, - vars.avgUncappedLtv + vars.hasZeroLtvCollateral ); } @@ -249,7 +221,7 @@ library GenericLogic { uint256, uint256, uint256, - uint256 + bool ) { return diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index 10b7a4f5..b8622466 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -507,19 +507,17 @@ library ValidationLogic { return (uint256(Errors.CollateralManagerErrors.NO_ERROR), Errors.LPCM_NO_ERRORS); } - struct validateHFAndExposureCapLocalVars { + struct validateHFAndLtvLocalVars { uint256 healthFactor; - uint256 ltv; - uint256 uncappedLtv; - uint256 exposureCap; + uint256 assetLtv; uint256 reserveDecimals; uint256 totalSupplyAtoken; + bool hasZeroLtvCollateral; } /** - * @dev Validates the health factor of a user and the exposure cap for the asset being withdrawn + * @dev Validates the health factor of a user and the ltv of the asset being withdrawn * @param asset The asset for which the exposure cap will be validated - * @param expCapOffset The offset to consider on the total atoken supply of asset when validating the exposure cap * @param from The user from which the aTokens are being transferred * @param reservesData The state of all the reserves * @param userConfig The state of the user for the specific reserve @@ -527,9 +525,8 @@ library ValidationLogic { * @param reservesCount The number of available reserves * @param oracle The price oracle */ - function validateHFAndExposureCap( + function validateHFAndLtv( address asset, - uint256 expCapOffset, address from, mapping(address => DataTypes.ReserveData) storage reservesData, DataTypes.UserConfigurationMap storage userConfig, @@ -537,9 +534,9 @@ library ValidationLogic { uint256 reservesCount, address oracle ) external view { - validateHFAndExposureCapLocalVars memory vars; + validateHFAndLtvLocalVars memory vars; DataTypes.ReserveData memory reserve = reservesData[asset]; - (, , vars.ltv, , vars.healthFactor, vars.uncappedLtv) = GenericLogic.calculateUserAccountData( + (, , , , vars.healthFactor, vars.hasZeroLtvCollateral) = GenericLogic.calculateUserAccountData( from, reservesData, userConfig, @@ -553,18 +550,9 @@ library ValidationLogic { Errors.VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD ); - vars.exposureCap = reserve.configuration.getExposureCapMemory(); + vars.assetLtv = reserve.configuration.getLtvMemory(); - if (vars.exposureCap != 0) { - if (vars.ltv < vars.uncappedLtv) { - vars.totalSupplyAtoken = IERC20(reserve.aTokenAddress).totalSupply(); - (, , , vars.reserveDecimals, ) = reserve.configuration.getParamsMemory(); - bool isAssetCapped = - vars.totalSupplyAtoken.sub(expCapOffset).div(10**vars.reserveDecimals) >= - vars.exposureCap; - require(isAssetCapped, Errors.VL_COLLATERAL_EXPOSURE_CAP_EXCEEDED); - } - } + require(vars.assetLtv == 0 || !vars.hasZeroLtvCollateral, Errors.VL_LTV_VALIDATION_FAILED); } /** From 7f3bf12d230fe551c93064910070056ff88bb66b Mon Sep 17 00:00:00 2001 From: The3D Date: Mon, 5 Jul 2021 19:55:56 +0200 Subject: [PATCH 2/4] docs: removed obsolete comment --- contracts/protocol/libraries/types/DataTypes.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/protocol/libraries/types/DataTypes.sol b/contracts/protocol/libraries/types/DataTypes.sol index 3c61c7af..1ed05d5d 100644 --- a/contracts/protocol/libraries/types/DataTypes.sol +++ b/contracts/protocol/libraries/types/DataTypes.sol @@ -43,7 +43,6 @@ library DataTypes { //bit 64-79: reserve factor //bit 80-115 borrow cap, borrowCap == 0 => disabled //bit 116-151 supply cap, supplyCap == 0 => disabled - //bit 152-185 exposure cap, exposureCap == 0 => disabled uint256 data; } From c1db1f8953598bb0236ef430ad64a1ee1a9bf513 Mon Sep 17 00:00:00 2001 From: The3D Date: Tue, 6 Jul 2021 18:51:08 +0200 Subject: [PATCH 3/4] tests: updated tests for the ltv validation --- .../protocol/libraries/logic/GenericLogic.sol | 2 +- .../libraries/logic/ValidationLogic.sol | 5 +- helpers/types.ts | 2 +- test-suites/test-aave/configurator.spec.ts | 159 +++------- test-suites/test-aave/exposure-cap.spec.ts | 276 ------------------ test-suites/test-aave/ltv-validation.spec.ts | 98 +++++++ 6 files changed, 138 insertions(+), 404 deletions(-) delete mode 100644 test-suites/test-aave/exposure-cap.spec.ts create mode 100644 test-suites/test-aave/ltv-validation.spec.ts diff --git a/contracts/protocol/libraries/logic/GenericLogic.sol b/contracts/protocol/libraries/logic/GenericLogic.sol index 1e6fa024..9bef0180 100644 --- a/contracts/protocol/libraries/logic/GenericLogic.sol +++ b/contracts/protocol/libraries/logic/GenericLogic.sol @@ -113,7 +113,7 @@ library GenericLogic { vars.totalCollateralInETH = vars.totalCollateralInETH.add(vars.userBalanceETH); vars.avgLtv = vars.avgLtv.add(vars.userBalanceETH.mul(vars.ltv)); - vars.hasZeroLtvCollateral = vars.ltv == 0; + vars.hasZeroLtvCollateral = vars.hasZeroLtvCollateral || vars.ltv == 0; vars.avgLiquidationThreshold = vars.avgLiquidationThreshold.add( vars.userBalanceETH.mul(vars.liquidationThreshold) ); diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index b8622466..7670a044 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -21,7 +21,7 @@ import {IAToken} from '../../../interfaces/IAToken.sol'; import {DataTypes} from '../types/DataTypes.sol'; import {IPriceOracleGetter} from '../../../interfaces/IPriceOracleGetter.sol'; import {Address} from '../../../dependencies/openzeppelin/contracts/Address.sol'; - +import "hardhat/console.sol"; /** * @title ReserveLogic library * @author Aave @@ -552,6 +552,9 @@ library ValidationLogic { vars.assetLtv = reserve.configuration.getLtvMemory(); + console.log("asset ltv is ", vars.assetLtv); + console.log("has 0 ltv collateral ", vars.hasZeroLtvCollateral); + require(vars.assetLtv == 0 || !vars.hasZeroLtvCollateral, Errors.VL_LTV_VALIDATION_FAILED); } diff --git a/helpers/types.ts b/helpers/types.ts index cff3f951..fe779211 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -189,7 +189,7 @@ export enum ProtocolErrors { RL_VARIABLE_DEBT_SUPPLY_NOT_ZERO = '90', LP_CALLER_NOT_EOA = '91', RC_INVALID_EXPOSURE_CAP = '92', - VL_COLLATERAL_EXPOSURE_CAP_EXCEEDED = '93', + VL_LTV_VALIDATION_FAILED = '93', VL_SAME_BLOCK_BORROW_REPAY = '94', LPC_FLASHLOAN_PREMIUMS_MISMATCH = '95', LPC_FLASHLOAN_PREMIUM_INVALID = '96', diff --git a/test-suites/test-aave/configurator.spec.ts b/test-suites/test-aave/configurator.spec.ts index 4eeab7bc..5b8ba9f9 100644 --- a/test-suites/test-aave/configurator.spec.ts +++ b/test-suites/test-aave/configurator.spec.ts @@ -229,7 +229,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -246,7 +246,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Unpauses the ETH reserve by pool admin ', async () => { @@ -264,7 +263,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -281,7 +280,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Pauses the ETH reserve by emergency admin', async () => { const { configurator, weth, helpersContract, addressesProvider, users, emergencyAdmin } = @@ -298,7 +296,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -315,7 +313,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Unpauses the ETH reserve by emergency admin ', async () => { @@ -333,7 +330,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -350,7 +347,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Check the only admin or emergency admin can pauseReserve ', async () => { @@ -384,7 +380,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -401,7 +397,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Unfreezes the ETH reserve by Pool admin', async () => { @@ -419,7 +414,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -436,8 +431,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); + it('Freezes the ETH reserve by Risk Admin', async () => { const { configurator, weth, helpersContract, riskAdmin } = testEnv; await configurator.connect(riskAdmin.signer).freezeReserve(weth.address); @@ -452,7 +447,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -469,7 +464,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Unfreezes the ETH reserve by Risk admin', async () => { @@ -487,7 +481,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -504,7 +498,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Check the onlyRiskOrPoolAdmins on freezeReserve ', async () => { @@ -537,7 +530,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -554,7 +547,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Activates the ETH reserve for borrowing via pool admin', async () => { @@ -573,7 +565,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -590,7 +582,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); expect(variableBorrowIndex.toString()).to.be.equal(RAY); }); @@ -609,7 +600,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -626,7 +617,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Activates the ETH reserve for borrowing via risk admin', async () => { @@ -645,7 +635,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -662,7 +652,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); expect(variableBorrowIndex.toString()).to.be.equal(RAY); }); @@ -701,7 +690,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -718,7 +707,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Activates the ETH reserve as collateral via pool admin', async () => { @@ -736,7 +724,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -753,8 +741,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); + it('Deactivates the ETH reserve as collateral via risk admin', async () => { const { configurator, helpersContract, weth, riskAdmin } = testEnv; await configurator @@ -772,7 +760,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -789,7 +777,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Activates the ETH reserve as collateral via risk admin', async () => { @@ -809,7 +796,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -826,7 +813,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Check the onlyRiskOrPoolAdmin on configureReserveAsCollateral ', async () => { @@ -853,7 +839,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -870,7 +856,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Enables stable borrow rate on the ETH reserve via pool admin', async () => { @@ -887,7 +872,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -904,8 +889,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); + it('Disable stable borrow rate on the ETH reserve risk admin', async () => { const { configurator, helpersContract, weth, riskAdmin } = testEnv; await configurator.connect(riskAdmin.signer).disableReserveStableRate(weth.address); @@ -920,7 +905,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -937,7 +922,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Enables stable borrow rate on the ETH reserve risk admin', async () => { @@ -954,7 +938,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -971,7 +955,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Check the onlyRiskOrPoolAdmin on disableReserveStableRate', async () => { @@ -1012,13 +995,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); }); - it('Check the onlyRiskOrPoolAdmin on setExposureCap', async () => { - const { configurator, users, weth, emergencyAdmin } = testEnv; - await expect( - configurator.connect(emergencyAdmin.signer).setExposureCap(weth.address, '3000000000'), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); - }); it('Changes the reserve factor of WETH via pool admin', async () => { const { configurator, helpersContract, weth } = testEnv; @@ -1034,7 +1010,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -1050,7 +1026,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); expect(reserveFactor).to.be.equal(1000); }); it('Changes the reserve factor of WETH risk admin', async () => { @@ -1067,7 +1042,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -1083,9 +1058,9 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); expect(reserveFactor).to.be.equal(1000); }); + it('Changes the reserve factor of WETH risk admin', async () => { const { configurator, helpersContract, weth, riskAdmin } = testEnv; await configurator.connect(riskAdmin.signer).setReserveFactor(weth.address, '1000'); @@ -1146,7 +1121,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -1163,8 +1138,9 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(1000); expect(borrowCap).to.be.equal('3000000'); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); + }); + it('Changes the borrow Cap of WETH risk admin', async () => { const { configurator, helpersContract, weth, riskAdmin } = testEnv; await configurator.connect(riskAdmin.signer).setBorrowCap(weth.address, '3000000'); @@ -1179,7 +1155,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -1196,7 +1172,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(1000); expect(borrowCap).to.be.equal('3000000'); expect(supplyCap).to.be.equal(strategyWETH.supplyCap); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); it('Changes the supply Cap of WETH via pool admin', async () => { @@ -1213,7 +1188,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -1230,8 +1205,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(1000); expect(borrowCap).to.be.equal('3000000'); expect(supplyCap).to.be.equal('3000000'); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); }); + it('Changes the supply Cap of WETH via risk admin', async () => { const { configurator, helpersContract, weth, riskAdmin } = testEnv; await configurator.connect(riskAdmin.signer).setSupplyCap(weth.address, '3000000'); @@ -1246,7 +1221,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps( weth.address ); const isPaused = await helpersContract.getPaused(weth.address); @@ -1263,74 +1238,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(1000); expect(borrowCap).to.be.equal('3000000'); expect(supplyCap).to.be.equal('3000000'); - expect(exposureCap).to.be.equal(strategyWETH.exposureCap); - }); - it('Changes the exposure Cap of WETH via pool admin', async () => { - const { configurator, helpersContract, weth } = testEnv; - await configurator.setExposureCap(weth.address, '3000000'); - const { - decimals, - ltv, - liquidationBonus, - liquidationThreshold, - reserveFactor, - stableBorrowRateEnabled, - borrowingEnabled, - isActive, - isFrozen, - } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( - weth.address - ); - const isPaused = await helpersContract.getPaused(weth.address); - - expect(borrowingEnabled).to.be.equal(true); - expect(isActive).to.be.equal(true); - expect(isPaused).to.be.equal(false); - expect(isFrozen).to.be.equal(false); - expect(decimals).to.be.equal(strategyWETH.reserveDecimals); - expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); - expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); - expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); - expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); - expect(reserveFactor).to.be.equal(1000); - expect(borrowCap).to.be.equal('3000000'); - expect(supplyCap).to.be.equal('3000000'); - expect(exposureCap).to.be.equal('3000000'); - }); - it('Changes the exposure Cap of WETH via risk admin', async () => { - const { configurator, helpersContract, weth, riskAdmin } = testEnv; - await configurator.connect(riskAdmin.signer).setExposureCap(weth.address, '3000000'); - const { - decimals, - ltv, - liquidationBonus, - liquidationThreshold, - reserveFactor, - stableBorrowRateEnabled, - borrowingEnabled, - isActive, - isFrozen, - } = await helpersContract.getReserveConfigurationData(weth.address); - const { borrowCap, supplyCap, exposureCap } = await helpersContract.getReserveCaps( - weth.address - ); - const isPaused = await helpersContract.getPaused(weth.address); - - expect(borrowingEnabled).to.be.equal(true); - expect(isActive).to.be.equal(true); - expect(isPaused).to.be.equal(false); - expect(isFrozen).to.be.equal(false); - expect(decimals).to.be.equal(strategyWETH.reserveDecimals); - expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); - expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); - expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); - expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); - expect(reserveFactor).to.be.equal(1000); - expect(borrowCap).to.be.equal('3000000'); - expect(supplyCap).to.be.equal('3000000'); - expect(exposureCap).to.be.equal('3000000'); }); + it('Changes the supply Cap of WETH via risk admin', async () => { const { configurator, helpersContract, weth, riskAdmin } = testEnv; await configurator.connect(riskAdmin.signer).setSupplyCap(weth.address, '3000000'); diff --git a/test-suites/test-aave/exposure-cap.spec.ts b/test-suites/test-aave/exposure-cap.spec.ts deleted file mode 100644 index 387043b0..00000000 --- a/test-suites/test-aave/exposure-cap.spec.ts +++ /dev/null @@ -1,276 +0,0 @@ -import { TestEnv, makeSuite } from './helpers/make-suite'; -import { - APPROVAL_AMOUNT_LENDING_POOL, - MAX_UINT_AMOUNT, - RAY, - MAX_EXPOSURE_CAP, - MOCK_CHAINLINK_AGGREGATORS_PRICES, -} from '../../helpers/constants'; -import { ProtocolErrors } from '../../helpers/types'; -import { MintableERC20, WETH9, WETH9Mocked } from '../../types'; -import { parseEther } from '@ethersproject/units'; -import { BigNumber } from '@ethersproject/bignumber'; -import { strategyDAI } from '../../markets/amm/reservesConfigs'; -import { strategyUSDC } from '../../markets/amm/reservesConfigs'; -import { ethers } from 'ethers'; - -const { expect } = require('chai'); -makeSuite('Exposure Cap', (testEnv: TestEnv) => { - const { - VL_COLLATERAL_EXPOSURE_CAP_EXCEEDED, - RC_INVALID_EXPOSURE_CAP, - VL_COLLATERAL_CANNOT_COVER_NEW_BORROW, - } = ProtocolErrors; - const daiPrice = Number(MOCK_CHAINLINK_AGGREGATORS_PRICES.DAI); - const usdcPrice = Number(MOCK_CHAINLINK_AGGREGATORS_PRICES.USDC); - const daiLTV = Number(strategyDAI.baseLTVAsCollateral); - const usdcLTV = Number(strategyUSDC.baseLTVAsCollateral); - - const unitParse = async (token: WETH9Mocked | MintableERC20, nb: string) => - BigNumber.from(nb).mul(BigNumber.from('10').pow((await token.decimals()) - 3)); - it('Reserves should initially have exposure cap disabled (exposureCap = 0)', async () => { - const { - weth, - pool, - dai, - usdc, - deployer, - helpersContract, - users: [user1], - } = testEnv; - - const mintedAmount = parseEther('1000000000'); - // minting for main user - await dai.mint(mintedAmount); - await weth.mint(mintedAmount); - await usdc.mint(mintedAmount); - // minting for lp user - await dai.connect(user1.signer).mint(mintedAmount); - await weth.connect(user1.signer).mint(mintedAmount); - await usdc.connect(user1.signer).mint(mintedAmount); - - await dai.approve(pool.address, MAX_UINT_AMOUNT); - await weth.approve(pool.address, MAX_UINT_AMOUNT); - await usdc.approve(pool.address, MAX_UINT_AMOUNT); - await dai.connect(user1.signer).approve(pool.address, MAX_UINT_AMOUNT); - await weth.connect(user1.signer).approve(pool.address, MAX_UINT_AMOUNT); - await usdc.connect(user1.signer).approve(pool.address, MAX_UINT_AMOUNT); - - await pool.deposit(weth.address, mintedAmount, deployer.address, 0); - - let usdcExposureCap = (await helpersContract.getReserveCaps(usdc.address)).exposureCap; - let daiExposureCap = (await helpersContract.getReserveCaps(dai.address)).exposureCap; - - expect(usdcExposureCap).to.be.equal('0'); - expect(daiExposureCap).to.be.equal('0'); - }); - it('Deposit 10 Dai, 10 USDC, LTV for both should increase', async () => { - const { - pool, - dai, - usdc, - users: [user1], - } = testEnv; - - const suppliedAmount = 10; - const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); - - // user 1 deposit more dai and usdc to be able to borrow - let { ltv } = await pool.getUserAccountData(user1.address); - expect(ltv.toString()).to.be.equal('0'); - await pool - .connect(user1.signer) - .deposit(dai.address, await unitParse(dai, precisionSuppliedAmount), user1.address, 0); - - ltv = (await pool.getUserAccountData(user1.address)).ltv; - expect(ltv).to.be.equal(daiLTV); - await pool - .connect(user1.signer) - .deposit(usdc.address, await unitParse(usdc, precisionSuppliedAmount), user1.address, 0); - - ltv = (await pool.getUserAccountData(user1.address)).ltv; - expect(Number(ltv)).to.be.equal( - Math.floor((daiLTV * daiPrice + usdcLTV * usdcPrice) / (daiPrice + usdcPrice)) - ); - }); - it('Sets the exposure cap for DAI to 10 Units', async () => { - const { - configurator, - dai, - helpersContract, - users: [], - } = testEnv; - - const newExposureCap = 10; - - await configurator.setExposureCap(dai.address, newExposureCap); - - const daiExposureCap = (await helpersContract.getReserveCaps(dai.address)).exposureCap; - - expect(daiExposureCap).to.be.equal(newExposureCap); - }); - it('should succeed to deposit 10 dai but dai ltv drops to 0', async () => { - const { - pool, - dai, - users: [user1], - } = testEnv; - const suppliedAmount = 10; - const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); - - await pool - .connect(user1.signer) - .deposit(dai.address, await unitParse(dai, precisionSuppliedAmount), user1.address, 0); - - let ltv = (await pool.getUserAccountData(user1.address)).ltv; - expect(ltv).to.be.equal(Math.floor((usdcLTV * usdcPrice) / (usdcPrice + 2 * daiPrice))); - }); - it('should succeed to deposit 1 dai but avg ltv decreases', async () => { - const { - pool, - dai, - users: [user1], - } = testEnv; - const suppliedAmount = 1; - const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); - let ltv = (await pool.getUserAccountData(user1.address)).ltv; - - await pool - .connect(user1.signer) - .deposit(dai.address, await unitParse(dai, precisionSuppliedAmount), user1.address, 0); - - expect(ltv.toNumber()).to.be.gt((await pool.getUserAccountData(user1.address)).ltv.toNumber()); - }); - it('should succeed to deposit 1 usdc and ltv should increase', async () => { - const { - usdc, - pool, - users: [user1], - } = testEnv; - const suppliedAmount = 1; - const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); - let ltv = (await pool.getUserAccountData(user1.address)).ltv; - - await pool - .connect(user1.signer) - .deposit(usdc.address, await unitParse(usdc, precisionSuppliedAmount), user1.address, 0); - - expect(ltv.toNumber()).to.be.lt((await pool.getUserAccountData(user1.address)).ltv.toNumber()); - }); - it('Should not be able to borrow 15 USD of weth', async () => { - const { - pool, - weth, - users: [user1], - } = testEnv; - const precisionBorrowedUsdAmount = 15 * 1000; - const precisionBorrowedEthAmount = ethers.BigNumber.from(precisionBorrowedUsdAmount) - .mul(daiPrice) - .div(parseEther('1.0')) - .toString(); - const borrowedAmount = await unitParse(weth, precisionBorrowedEthAmount); - - await expect( - pool.connect(user1.signer).borrow(weth.address, borrowedAmount, 1, 0, user1.address) - ).to.be.revertedWith(VL_COLLATERAL_CANNOT_COVER_NEW_BORROW); - }); - it('should be able to borrow 15 USD of weth after dai exposure cap raised to 100', async () => { - const { - pool, - dai, - weth, - configurator, - helpersContract, - users: [user1], - } = testEnv; - - const newExposureCap = 100; - - await configurator.setExposureCap(dai.address, newExposureCap); - - const daiExposureCap = (await helpersContract.getReserveCaps(dai.address)).exposureCap; - - expect(daiExposureCap).to.be.equal(newExposureCap); - - const precisionBorrowedUsdAmount = 15 * 1000; - const precisionBorrowedEthAmount = ethers.BigNumber.from(precisionBorrowedUsdAmount) - .mul(daiPrice) - .div(parseEther('1.0')) - .toString(); - const borrowedAmount = await unitParse(weth, precisionBorrowedEthAmount); - - pool.connect(user1.signer).borrow(weth.address, borrowedAmount, 1, 0, user1.address); - }); - it('should not be able to withdraw 5 dai, transfer 5 aDai after cap decrease of usdc back to 10 (capped)', async () => { - const { - pool, - dai, - usdc, - aDai, - configurator, - helpersContract, - users: [user1, , , receiver], - } = testEnv; - - const newExposureCap = 10; - - await configurator.setExposureCap(usdc.address, newExposureCap); - - const usdcExposureCap = (await helpersContract.getReserveCaps(usdc.address)).exposureCap; - - expect(usdcExposureCap).to.be.equal(newExposureCap); - - const precisionWithdrawnAmount = (5 * 1000).toString(); - const withdrawnAmount = await unitParse(dai, precisionWithdrawnAmount); - - await expect( - pool.connect(user1.signer).withdraw(dai.address, withdrawnAmount, user1.address) - ).to.be.revertedWith(VL_COLLATERAL_EXPOSURE_CAP_EXCEEDED); - await expect( - aDai.connect(user1.signer).transfer(receiver.address, withdrawnAmount) - ).to.be.revertedWith(VL_COLLATERAL_EXPOSURE_CAP_EXCEEDED); - }); - it('should be able to withdraw 5 usdc and transfer 5 aUsdc', async () => { - const { - usdc, - pool, - aUsdc, - users: [user1, , , receiver], - } = testEnv; - - const precisionWithdrawnAmount = (5 * 1000).toString(); - const withdrawnAmount = await unitParse(usdc, precisionWithdrawnAmount); - - await pool.connect(user1.signer).withdraw(usdc.address, withdrawnAmount, user1.address); - await aUsdc.connect(user1.signer).transfer(receiver.address, withdrawnAmount); - }); - it('should be able to withdraw 5 dai, transfer 5 aDai after repaying weth Debt', async () => { - const { - pool, - dai, - weth, - aDai, - users: [user1, , , receiver], - } = testEnv; - - const precisionWithdrawnAmount = (5 * 1000).toString(); - const withdrawnAmount = await unitParse(dai, precisionWithdrawnAmount); - await ( - await pool.connect(user1.signer).repay(weth.address, MAX_UINT_AMOUNT, 1, user1.address) - ).wait(); - - pool.connect(user1.signer).withdraw(dai.address, withdrawnAmount, user1.address); - aDai.connect(user1.signer).transfer(receiver.address, withdrawnAmount); - }); - it('Should fail to set the exposure cap for usdc and DAI to max cap + 1 Units', async () => { - const { configurator, usdc, dai } = testEnv; - const newCap = Number(MAX_EXPOSURE_CAP) + 1; - - await expect(configurator.setExposureCap(usdc.address, newCap)).to.be.revertedWith( - RC_INVALID_EXPOSURE_CAP - ); - await expect(configurator.setExposureCap(dai.address, newCap)).to.be.revertedWith( - RC_INVALID_EXPOSURE_CAP - ); - }); -}); diff --git a/test-suites/test-aave/ltv-validation.spec.ts b/test-suites/test-aave/ltv-validation.spec.ts new file mode 100644 index 00000000..56e90074 --- /dev/null +++ b/test-suites/test-aave/ltv-validation.spec.ts @@ -0,0 +1,98 @@ +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { + APPROVAL_AMOUNT_LENDING_POOL, + MAX_UINT_AMOUNT, + RAY, + MAX_EXPOSURE_CAP, + MOCK_CHAINLINK_AGGREGATORS_PRICES, + oneEther, +} from '../../helpers/constants'; +import { ProtocolErrors } from '../../helpers/types'; +import { MintableERC20, WETH9, WETH9Mocked } from '../../types'; +import { parseEther } from '@ethersproject/units'; +import { BigNumber } from '@ethersproject/bignumber'; +import { strategyDAI } from '../../markets/amm/reservesConfigs'; +import { strategyUSDC } from '../../markets/amm/reservesConfigs'; +import { ethers } from 'ethers'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; + +const { expect } = require('chai'); +makeSuite('LTV validation tests', (testEnv: TestEnv) => { + const { + VL_LTV_VALIDATION_FAILED, + RC_INVALID_EXPOSURE_CAP, + VL_COLLATERAL_CANNOT_COVER_NEW_BORROW, + } = ProtocolErrors; + const daiPrice = Number(MOCK_CHAINLINK_AGGREGATORS_PRICES.DAI); + const usdcPrice = Number(MOCK_CHAINLINK_AGGREGATORS_PRICES.USDC); + const daiLTV = Number(strategyDAI.baseLTVAsCollateral); + const usdcLTV = Number(strategyUSDC.baseLTVAsCollateral); + + it('User 1 deposits 10 Dai, 10 USDC, user 2 deposits 1 WETH', async () => { + const { + pool, + dai, + usdc, + weth, + users: [user1, user2], + } = testEnv; + + const daiAmount = await convertToCurrencyDecimals(dai.address, '10'); + const usdcAmount = await convertToCurrencyDecimals(usdc.address, '10'); + const wethAmount = await convertToCurrencyDecimals(weth.address, '1'); + + await dai.connect(user1.signer).approve(pool.address, MAX_UINT_AMOUNT); + await usdc.connect(user1.signer).approve(pool.address, MAX_UINT_AMOUNT); + await weth.connect(user2.signer).approve(pool.address, MAX_UINT_AMOUNT); + + await dai.connect(user1.signer).mint(daiAmount); + await usdc.connect(user1.signer).mint(usdcAmount); + await weth.connect(user2.signer).mint(wethAmount); + + await pool.connect(user1.signer).deposit(dai.address, daiAmount, user1.address, 0); + + await pool.connect(user1.signer).deposit(usdc.address, usdcAmount, user1.address, 0); + + await pool.connect(user2.signer).deposit(weth.address, wethAmount, user2.address, 0); + }); + + it('Sets the ltv of DAI to 0', async () => { + const { + configurator, + dai, + helpersContract, + users: [], + } = testEnv; + + await configurator.configureReserveAsCollateral(dai.address, 0, 8000, 10500); + + const ltv = (await helpersContract.getReserveConfigurationData(dai.address)).ltv; + + expect(ltv).to.be.equal(0); + }); + + it('Borrows 0.01 weth', async () => { + const { + pool, + weth, + users: [user1], + } = testEnv; + const borrowedAmount = await convertToCurrencyDecimals(weth.address, "0.01"); + + pool.connect(user1.signer).borrow(weth.address, borrowedAmount, 1, 0, user1.address); + }); + + it('Tries to withdraw USDC (revert expected)', async () => { + const { + pool, + usdc, + users: [user1, , , receiver], + } = testEnv; + + const withdrawnAmount = await convertToCurrencyDecimals(usdc.address, "1"); + + await expect( + pool.connect(user1.signer).withdraw(usdc.address, withdrawnAmount, user1.address) + ).to.be.revertedWith(VL_LTV_VALIDATION_FAILED); + }); +}); From 89e03892f1307e00f36954fda4f2aff6d2f67f26 Mon Sep 17 00:00:00 2001 From: emilio Date: Sun, 11 Jul 2021 20:00:45 +0200 Subject: [PATCH 4/4] refactor: refactored tests, removed last exposure ceiling references --- .../protocol/libraries/helpers/Errors.sol | 1 - .../protocol/libraries/logic/GenericLogic.sol | 2 +- .../libraries/logic/ValidationLogic.sol | 7 +--- helpers/constants.ts | 1 - helpers/init-helpers.ts | 3 -- helpers/types.ts | 2 - markets/aave/reservesConfigs.ts | 42 +++++++++---------- markets/amm/reservesConfigs.ts | 40 +++++++++--------- markets/matic/reservesConfigs.ts | 14 +++---- test-suites/test-aave/configurator.spec.ts | 10 ++--- test-suites/test-aave/ltv-validation.spec.ts | 40 ++++++++++-------- 11 files changed, 78 insertions(+), 84 deletions(-) diff --git a/contracts/protocol/libraries/helpers/Errors.sol b/contracts/protocol/libraries/helpers/Errors.sol index b4c14221..36ac923a 100644 --- a/contracts/protocol/libraries/helpers/Errors.sol +++ b/contracts/protocol/libraries/helpers/Errors.sol @@ -113,7 +113,6 @@ library Errors { string public constant RL_STABLE_DEBT_NOT_ZERO = '89'; string public constant RL_VARIABLE_DEBT_SUPPLY_NOT_ZERO = '90'; string public constant LP_CALLER_NOT_EOA = '91'; - string public constant RC_INVALID_EXPOSURE_CAP = '92'; string public constant VL_LTV_VALIDATION_FAILED = '93'; string public constant VL_SAME_BLOCK_BORROW_REPAY = '94'; string public constant LPC_FLASHLOAN_PREMIUMS_MISMATCH = '95'; diff --git a/contracts/protocol/libraries/logic/GenericLogic.sol b/contracts/protocol/libraries/logic/GenericLogic.sol index 9bef0180..bcb49b24 100644 --- a/contracts/protocol/libraries/logic/GenericLogic.sol +++ b/contracts/protocol/libraries/logic/GenericLogic.sol @@ -60,7 +60,7 @@ library GenericLogic { * @param userConfig The configuration of the user * @param reserves The list of the available reserves * @param oracle The price oracle address - * @return The total collateral and total debt of the user in ETH, the avg ltv, liquidation threshold, the HF and the uncapped avg ltv (without exposure ceiling) + * @return The total collateral and total debt of the user in ETH, the avg ltv, liquidation threshold, the HF and the uncapped avg ltv **/ function calculateUserAccountData( address user, diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index 7670a044..4fc4596e 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -21,7 +21,7 @@ import {IAToken} from '../../../interfaces/IAToken.sol'; import {DataTypes} from '../types/DataTypes.sol'; import {IPriceOracleGetter} from '../../../interfaces/IPriceOracleGetter.sol'; import {Address} from '../../../dependencies/openzeppelin/contracts/Address.sol'; -import "hardhat/console.sol"; + /** * @title ReserveLogic library * @author Aave @@ -517,7 +517,7 @@ library ValidationLogic { /** * @dev Validates the health factor of a user and the ltv of the asset being withdrawn - * @param asset The asset for which the exposure cap will be validated + * @param asset The asset for which the ltv will be validated * @param from The user from which the aTokens are being transferred * @param reservesData The state of all the reserves * @param userConfig The state of the user for the specific reserve @@ -552,9 +552,6 @@ library ValidationLogic { vars.assetLtv = reserve.configuration.getLtvMemory(); - console.log("asset ltv is ", vars.assetLtv); - console.log("has 0 ltv collateral ", vars.hasZeroLtvCollateral); - require(vars.assetLtv == 0 || !vars.hasZeroLtvCollateral, Errors.VL_LTV_VALIDATION_FAILED); } diff --git a/helpers/constants.ts b/helpers/constants.ts index b25ce643..f2568ee0 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -17,7 +17,6 @@ export const MAX_UINT_AMOUNT = '115792089237316195423570985008687907853269984665640564039457584007913129639935'; export const MAX_BORROW_CAP = '68719476735'; export const MAX_SUPPLY_CAP = '68719476735'; -export const MAX_EXPOSURE_CAP = '68719476735'; export const ONE_YEAR = '31536000'; export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; export const ONE_ADDRESS = '0x0000000000000000000000000000000000000001'; diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 4289e68a..dc731b17 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -285,7 +285,6 @@ export const configureReservesByHelper = async ( reserveFactor: BigNumberish; borrowCap: BigNumberish; supplyCap: BigNumberish; - exposureCap: BigNumberish; stableBorrowingEnabled: boolean; borrowingEnabled: boolean; }[] = []; @@ -299,7 +298,6 @@ export const configureReservesByHelper = async ( reserveFactor, borrowCap, supplyCap, - exposureCap, stableBorrowRateEnabled, borrowingEnabled, }, @@ -336,7 +334,6 @@ export const configureReservesByHelper = async ( reserveFactor, borrowCap, supplyCap, - exposureCap, stableBorrowingEnabled: stableBorrowRateEnabled, borrowingEnabled: borrowingEnabled, }); diff --git a/helpers/types.ts b/helpers/types.ts index fe779211..68d1ac23 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -188,7 +188,6 @@ export enum ProtocolErrors { RL_STABLE_DEBT_NOT_ZERO = '89', RL_VARIABLE_DEBT_SUPPLY_NOT_ZERO = '90', LP_CALLER_NOT_EOA = '91', - RC_INVALID_EXPOSURE_CAP = '92', VL_LTV_VALIDATION_FAILED = '93', VL_SAME_BLOCK_BORROW_REPAY = '94', LPC_FLASHLOAN_PREMIUMS_MISMATCH = '95', @@ -403,7 +402,6 @@ export interface IReserveCollateralParams { baseLTVAsCollateral: string; liquidationThreshold: string; liquidationBonus: string; - exposureCap: string; } export interface IMarketRates { borrowRate: string; diff --git a/markets/aave/reservesConfigs.ts b/markets/aave/reservesConfigs.ts index cd48a26c..8c04a3c8 100644 --- a/markets/aave/reservesConfigs.ts +++ b/markets/aave/reservesConfigs.ts @@ -24,7 +24,7 @@ export const strategyBUSD: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyDAI: IReserveParams = { @@ -39,7 +39,7 @@ export const strategyDAI: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategySUSD: IReserveParams = { @@ -54,7 +54,7 @@ export const strategySUSD: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyTUSD: IReserveParams = { @@ -69,7 +69,7 @@ export const strategyTUSD: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyUSDC: IReserveParams = { @@ -84,7 +84,7 @@ export const strategyUSDC: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyUSDT: IReserveParams = { @@ -99,7 +99,7 @@ export const strategyUSDT: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyAAVE: IReserveParams = { @@ -114,7 +114,7 @@ export const strategyAAVE: IReserveParams = { reserveFactor: '0', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyBAT: IReserveParams = { @@ -129,7 +129,7 @@ export const strategyBAT: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyENJ: IReserveParams = { @@ -144,7 +144,7 @@ export const strategyENJ: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyWETH: IReserveParams = { @@ -159,7 +159,7 @@ export const strategyWETH: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyKNC: IReserveParams = { @@ -174,7 +174,7 @@ export const strategyKNC: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyLINK: IReserveParams = { @@ -189,7 +189,7 @@ export const strategyLINK: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyMANA: IReserveParams = { @@ -204,7 +204,7 @@ export const strategyMANA: IReserveParams = { reserveFactor: '3500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyMKR: IReserveParams = { @@ -219,7 +219,7 @@ export const strategyMKR: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyREN: IReserveParams = { @@ -234,7 +234,7 @@ export const strategyREN: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategySNX: IReserveParams = { @@ -249,7 +249,7 @@ export const strategySNX: IReserveParams = { reserveFactor: '3500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; // Invalid borrow rates in params currently, replaced with snx params @@ -265,7 +265,7 @@ export const strategyUNI: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyWBTC: IReserveParams = { @@ -280,7 +280,7 @@ export const strategyWBTC: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyYFI: IReserveParams = { @@ -295,7 +295,7 @@ export const strategyYFI: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyZRX: IReserveParams = { @@ -310,7 +310,7 @@ export const strategyZRX: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyXSUSHI: IReserveParams = { @@ -325,5 +325,5 @@ export const strategyXSUSHI: IReserveParams = { reserveFactor: '3500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; diff --git a/markets/amm/reservesConfigs.ts b/markets/amm/reservesConfigs.ts index fcbf8280..22a25020 100644 --- a/markets/amm/reservesConfigs.ts +++ b/markets/amm/reservesConfigs.ts @@ -13,7 +13,7 @@ export const strategyWETH: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyWBTC: IReserveParams = { @@ -28,7 +28,7 @@ export const strategyWBTC: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyDAI: IReserveParams = { @@ -43,7 +43,7 @@ export const strategyDAI: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyUSDC: IReserveParams = { @@ -58,7 +58,7 @@ export const strategyUSDC: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyUSDT: IReserveParams = { @@ -73,7 +73,7 @@ export const strategyUSDT: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyDAIWETH: IReserveParams = { @@ -88,7 +88,7 @@ export const strategyDAIWETH: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyWBTCWETH: IReserveParams = { @@ -103,7 +103,7 @@ export const strategyWBTCWETH: IReserveParams = { reserveFactor: '1500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyAAVEWETH: IReserveParams = { @@ -118,7 +118,7 @@ export const strategyAAVEWETH: IReserveParams = { reserveFactor: '500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyBATWETH: IReserveParams = { @@ -133,7 +133,7 @@ export const strategyBATWETH: IReserveParams = { reserveFactor: '1500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyDAIUSDC: IReserveParams = { @@ -148,7 +148,7 @@ export const strategyDAIUSDC: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyCRVWETH: IReserveParams = { @@ -163,7 +163,7 @@ export const strategyCRVWETH: IReserveParams = { reserveFactor: '1500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyLINKWETH: IReserveParams = { @@ -178,7 +178,7 @@ export const strategyLINKWETH: IReserveParams = { reserveFactor: '1500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyMKRWETH: IReserveParams = { @@ -193,7 +193,7 @@ export const strategyMKRWETH: IReserveParams = { reserveFactor: '1500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyRENWETH: IReserveParams = { @@ -208,7 +208,7 @@ export const strategyRENWETH: IReserveParams = { reserveFactor: '1500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategySNXWETH: IReserveParams = { @@ -223,7 +223,7 @@ export const strategySNXWETH: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyUNIWETH: IReserveParams = { @@ -238,7 +238,7 @@ export const strategyUNIWETH: IReserveParams = { reserveFactor: '1500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyUSDCWETH: IReserveParams = { @@ -253,7 +253,7 @@ export const strategyUSDCWETH: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyWBTCUSDC: IReserveParams = { @@ -268,7 +268,7 @@ export const strategyWBTCUSDC: IReserveParams = { reserveFactor: '1500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyYFIWETH: IReserveParams = { @@ -283,7 +283,7 @@ export const strategyYFIWETH: IReserveParams = { reserveFactor: '1500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyBALWETH: IReserveParams = { @@ -298,5 +298,5 @@ export const strategyBALWETH: IReserveParams = { reserveFactor: '1500', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; diff --git a/markets/matic/reservesConfigs.ts b/markets/matic/reservesConfigs.ts index 0c9da5af..91fee5db 100644 --- a/markets/matic/reservesConfigs.ts +++ b/markets/matic/reservesConfigs.ts @@ -22,7 +22,7 @@ export const strategyDAI: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyUSDC: IReserveParams = { @@ -37,7 +37,7 @@ export const strategyUSDC: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyUSDT: IReserveParams = { @@ -52,7 +52,7 @@ export const strategyUSDT: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyWETH: IReserveParams = { @@ -67,7 +67,7 @@ export const strategyWETH: IReserveParams = { reserveFactor: '1000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyWBTC: IReserveParams = { @@ -82,7 +82,7 @@ export const strategyWBTC: IReserveParams = { reserveFactor: '2000', borrowCap: '0', supplyCap: '0', - exposureCap: '0', + }; export const strategyMATIC: IReserveParams = { @@ -96,7 +96,7 @@ export const strategyMATIC: IReserveParams = { aTokenImpl: eContractid.AToken, borrowCap: '0', supplyCap: '0', - exposureCap: '0', + reserveFactor: '2000', }; @@ -111,6 +111,6 @@ export const strategyAAVE: IReserveParams = { aTokenImpl: eContractid.AToken, borrowCap: '0', supplyCap: '0', - exposureCap: '0', + reserveFactor: '0', }; diff --git a/test-suites/test-aave/configurator.spec.ts b/test-suites/test-aave/configurator.spec.ts index 5b8ba9f9..59c7764b 100644 --- a/test-suites/test-aave/configurator.spec.ts +++ b/test-suites/test-aave/configurator.spec.ts @@ -677,7 +677,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { it('Deactivates the ETH reserve as collateral via pool admin', async () => { const { configurator, helpersContract, weth } = testEnv; - await configurator.configureReserveAsCollateral(weth.address, 0, 0, 0, 0); + await configurator.configureReserveAsCollateral(weth.address, 0, 0, 0); const { decimals, @@ -711,7 +711,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { it('Activates the ETH reserve as collateral via pool admin', async () => { const { configurator, helpersContract, weth } = testEnv; - await configurator.configureReserveAsCollateral(weth.address, '8000', '8250', '10500', '0'); + await configurator.configureReserveAsCollateral(weth.address, '8000', '8250', '10500'); const { decimals, @@ -747,7 +747,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { const { configurator, helpersContract, weth, riskAdmin } = testEnv; await configurator .connect(riskAdmin.signer) - .configureReserveAsCollateral(weth.address, 0, 0, 0, 0); + .configureReserveAsCollateral(weth.address, 0, 0, 0); const { decimals, @@ -783,7 +783,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { const { configurator, helpersContract, weth, riskAdmin } = testEnv; await configurator .connect(riskAdmin.signer) - .configureReserveAsCollateral(weth.address, '8000', '8250', '10500', '0'); + .configureReserveAsCollateral(weth.address, '8000', '8250', '10500'); const { decimals, @@ -820,7 +820,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { await expect( configurator .connect(emergencyAdmin.signer) - .configureReserveAsCollateral(weth.address, '7500', '8000', '10500', '0'), + .configureReserveAsCollateral(weth.address, '7500', '8000', '10500'), CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); }); diff --git a/test-suites/test-aave/ltv-validation.spec.ts b/test-suites/test-aave/ltv-validation.spec.ts index 56e90074..1017fbec 100644 --- a/test-suites/test-aave/ltv-validation.spec.ts +++ b/test-suites/test-aave/ltv-validation.spec.ts @@ -1,32 +1,15 @@ import { TestEnv, makeSuite } from './helpers/make-suite'; import { - APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, - RAY, - MAX_EXPOSURE_CAP, - MOCK_CHAINLINK_AGGREGATORS_PRICES, - oneEther, } from '../../helpers/constants'; import { ProtocolErrors } from '../../helpers/types'; -import { MintableERC20, WETH9, WETH9Mocked } from '../../types'; -import { parseEther } from '@ethersproject/units'; -import { BigNumber } from '@ethersproject/bignumber'; -import { strategyDAI } from '../../markets/amm/reservesConfigs'; -import { strategyUSDC } from '../../markets/amm/reservesConfigs'; -import { ethers } from 'ethers'; import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; const { expect } = require('chai'); makeSuite('LTV validation tests', (testEnv: TestEnv) => { const { VL_LTV_VALIDATION_FAILED, - RC_INVALID_EXPOSURE_CAP, - VL_COLLATERAL_CANNOT_COVER_NEW_BORROW, } = ProtocolErrors; - const daiPrice = Number(MOCK_CHAINLINK_AGGREGATORS_PRICES.DAI); - const usdcPrice = Number(MOCK_CHAINLINK_AGGREGATORS_PRICES.USDC); - const daiLTV = Number(strategyDAI.baseLTVAsCollateral); - const usdcLTV = Number(strategyUSDC.baseLTVAsCollateral); it('User 1 deposits 10 Dai, 10 USDC, user 2 deposits 1 WETH', async () => { const { @@ -86,7 +69,7 @@ makeSuite('LTV validation tests', (testEnv: TestEnv) => { const { pool, usdc, - users: [user1, , , receiver], + users: [user1], } = testEnv; const withdrawnAmount = await convertToCurrencyDecimals(usdc.address, "1"); @@ -95,4 +78,25 @@ makeSuite('LTV validation tests', (testEnv: TestEnv) => { pool.connect(user1.signer).withdraw(usdc.address, withdrawnAmount, user1.address) ).to.be.revertedWith(VL_LTV_VALIDATION_FAILED); }); + + it('Withdraws DAI', async () => { + const { + pool, + dai, + aDai, + users: [user1], + } = testEnv; + + const aDaiBalanceBefore = await aDai.balanceOf(user1.address); + + const withdrawnAmount = await convertToCurrencyDecimals(dai.address, "1"); + + await pool.connect(user1.signer).withdraw(dai.address, withdrawnAmount, user1.address); + + const aDaiBalanceAfter = await aDai.balanceOf(user1.address); + + expect(aDaiBalanceAfter.toString()).to.be.bignumber.equal(aDaiBalanceBefore.sub(withdrawnAmount)); + + }); + });