From 4ce1bfcb8c476351a8a99950b07a874ca0939f79 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 23 Apr 2021 17:32:07 +0200 Subject: [PATCH 01/34] feat: added borrow cap to config --- contracts/misc/AaveProtocolDataProvider.sol | 12 +++-- contracts/misc/UiPoolDataProvider.sol | 3 +- .../misc/interfaces/IUiPoolDataProvider.sol | 1 + .../LendingPoolCollateralManager.sol | 2 +- .../lendingpool/LendingPoolConfigurator.sol | 6 +-- .../configuration/ReserveConfiguration.sol | 46 +++++++++++++++++-- .../protocol/libraries/helpers/Errors.sol | 1 + .../protocol/libraries/logic/GenericLogic.sol | 4 +- .../protocol/libraries/types/DataTypes.sol | 1 + 9 files changed, 59 insertions(+), 17 deletions(-) diff --git a/contracts/misc/AaveProtocolDataProvider.sol b/contracts/misc/AaveProtocolDataProvider.sol index 56f7c96e..494ee304 100644 --- a/contracts/misc/AaveProtocolDataProvider.sol +++ b/contracts/misc/AaveProtocolDataProvider.sol @@ -73,6 +73,7 @@ contract AaveProtocolDataProvider { uint256 liquidationThreshold, uint256 liquidationBonus, uint256 reserveFactor, + uint256 borrowCap, bool usageAsCollateralEnabled, bool borrowingEnabled, bool stableBorrowRateEnabled, @@ -80,13 +81,14 @@ contract AaveProtocolDataProvider { bool isFrozen ) { - DataTypes.ReserveConfigurationMap memory configuration = - ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getConfiguration(asset); - - (ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor) = configuration + (ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor, ) = + ILendingPool(ADDRESSES_PROVIDER.getLendingPool()) + .getConfiguration(asset) .getParamsMemory(); - (isActive, isFrozen, borrowingEnabled, stableBorrowRateEnabled) = configuration + (isActive, isFrozen, borrowingEnabled, stableBorrowRateEnabled) = + ILendingPool(ADDRESSES_PROVIDER.getLendingPool()) + .getConfiguration(asset) .getFlagsMemory(); usageAsCollateralEnabled = liquidationThreshold > 0; diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 65fdc4dd..b59da60f 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -104,7 +104,8 @@ contract UiPoolDataProvider is IUiPoolDataProvider { reserveData.reserveLiquidationThreshold, reserveData.reserveLiquidationBonus, reserveData.decimals, - reserveData.reserveFactor + reserveData.reserveFactor, + reserveData.borrowCap ) = baseData.configuration.getParamsMemory(); ( reserveData.isActive, diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index 81a553e8..a93c0a43 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -14,6 +14,7 @@ interface IUiPoolDataProvider { uint256 reserveLiquidationThreshold; uint256 reserveLiquidationBonus; uint256 reserveFactor; + uint256 borrowCap; bool usageAsCollateralEnabled; bool borrowingEnabled; bool stableBorrowRateEnabled; diff --git a/contracts/protocol/lendingpool/LendingPoolCollateralManager.sol b/contracts/protocol/lendingpool/LendingPoolCollateralManager.sol index 80692726..53e8fc52 100644 --- a/contracts/protocol/lendingpool/LendingPoolCollateralManager.sol +++ b/contracts/protocol/lendingpool/LendingPoolCollateralManager.sol @@ -286,7 +286,7 @@ contract LendingPoolCollateralManager is vars.collateralPrice = oracle.getAssetPrice(collateralAsset); vars.debtAssetPrice = oracle.getAssetPrice(debtAsset); - (, , vars.liquidationBonus, vars.collateralDecimals, ) = collateralReserve + (, , vars.liquidationBonus, vars.collateralDecimals, , ) = collateralReserve .configuration .getParams(); vars.debtAssetDecimals = debtReserve.configuration.getDecimals(); diff --git a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol index 49451d92..ec35b180 100644 --- a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol @@ -149,7 +149,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); - (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); + (, , , uint256 decimals, , ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); bytes memory encodedCall = abi.encodeWithSelector( IInitializableAToken.initialize.selector, @@ -180,7 +180,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); - (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); + (, , , uint256 decimals, , ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); bytes memory encodedCall = abi.encodeWithSelector( IInitializableDebtToken.initialize.selector, @@ -217,7 +217,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); - (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); + (, , , uint256 decimals, , ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); bytes memory encodedCall = abi.encodeWithSelector( IInitializableDebtToken.initialize.selector, diff --git a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol index 5649a580..188bee66 100644 --- a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol @@ -19,6 +19,7 @@ library ReserveConfiguration { uint256 constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore + uint256 constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF; // 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; @@ -29,12 +30,14 @@ library ReserveConfiguration { uint256 constant BORROWING_ENABLED_START_BIT_POSITION = 58; uint256 constant STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59; uint256 constant RESERVE_FACTOR_START_BIT_POSITION = 64; + uint256 constant BORROW_CAP_START_BIT_POSITION = 80; uint256 constant MAX_VALID_LTV = 65535; uint256 constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535; uint256 constant MAX_VALID_LIQUIDATION_BONUS = 65535; uint256 constant MAX_VALID_DECIMALS = 255; uint256 constant MAX_VALID_RESERVE_FACTOR = 65535; + uint256 constant MAX_VALID_BORROW_CAP = 65535; /** * @dev Sets the Loan to Value of the reserve @@ -264,6 +267,35 @@ library ReserveConfiguration { return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION; } + /** + * @dev Sets the borrow cap of the reserve + * @param self The reserve configuration + * @param borrowCap The borrow cap + **/ + function setBorrowCap(DataTypes.ReserveConfigurationMap memory self, uint256 borrowCap) + internal + pure + { + require(borrowCap <= MAX_VALID_BORROW_CAP, Errors.RC_INVALID_BORROW_CAP); + + self.data = + (self.data & BORROW_CAP_MASK) | + (borrowCap << BORROW_CAP_START_BIT_POSITION); + } + + /** + * @dev Gets the borrow cap of the reserve + * @param self The reserve configuration + * @return The borrow cap + **/ + function getBorrowCap(DataTypes.ReserveConfigurationMap storage self) + internal + view + returns (uint256) + { + return (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION; + } + /** * @dev Gets the configuration flags of the reserve * @param self The reserve configuration @@ -290,9 +322,9 @@ library ReserveConfiguration { } /** - * @dev Gets the configuration paramters of the reserve + * @dev Gets the configuration paramters of the reserve from storage * @param self The reserve configuration - * @return The state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals + * @return The state params representing ltv, liquidation threshold, liquidation bonus, reserve decimals, reserve factor and borrow cap. **/ function getParams(DataTypes.ReserveConfigurationMap storage self) internal @@ -302,6 +334,7 @@ library ReserveConfiguration { uint256, uint256, uint256, + uint256, uint256 ) { @@ -312,14 +345,15 @@ library ReserveConfiguration { (dataLocal & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION, (dataLocal & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION, (dataLocal & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION, - (dataLocal & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION + (dataLocal & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION, + (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION ); } /** * @dev Gets the configuration paramters of the reserve from a memory object * @param self The reserve configuration - * @return The state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals + * @return The state params representing ltv, liquidation threshold, liquidation bonus, reserve decimals, reserve factor, borrow cap **/ function getParamsMemory(DataTypes.ReserveConfigurationMap memory self) internal @@ -329,6 +363,7 @@ library ReserveConfiguration { uint256, uint256, uint256, + uint256, uint256 ) { @@ -337,7 +372,8 @@ library ReserveConfiguration { (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION, (self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION, (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION, - (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION + (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION, + (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION ); } diff --git a/contracts/protocol/libraries/helpers/Errors.sol b/contracts/protocol/libraries/helpers/Errors.sol index 8756d797..304f0a33 100644 --- a/contracts/protocol/libraries/helpers/Errors.sol +++ b/contracts/protocol/libraries/helpers/Errors.sol @@ -103,6 +103,7 @@ library Errors { string public constant LP_NOT_CONTRACT = '78'; string public constant SDT_STABLE_DEBT_OVERFLOW = '79'; string public constant SDT_BURN_EXCEEDS_BALANCE = '80'; + string public constant RC_INVALID_BORROW_CAP = '82'; enum CollateralManagerErrors { NO_ERROR, diff --git a/contracts/protocol/libraries/logic/GenericLogic.sol b/contracts/protocol/libraries/logic/GenericLogic.sol index d4081dda..9f457a17 100644 --- a/contracts/protocol/libraries/logic/GenericLogic.sol +++ b/contracts/protocol/libraries/logic/GenericLogic.sol @@ -68,7 +68,7 @@ library GenericLogic { balanceDecreaseAllowedLocalVars memory vars; - (, vars.liquidationThreshold, , vars.decimals, ) = reservesData[asset] + (, vars.liquidationThreshold, , vars.decimals, , ) = reservesData[asset] .configuration .getParams(); @@ -178,7 +178,7 @@ library GenericLogic { vars.currentReserveAddress = reserves[vars.i]; DataTypes.ReserveData storage currentReserve = reservesData[vars.currentReserveAddress]; - (vars.ltv, vars.liquidationThreshold, , vars.decimals, ) = currentReserve + (vars.ltv, vars.liquidationThreshold, , vars.decimals, , ) = currentReserve .configuration .getParams(); diff --git a/contracts/protocol/libraries/types/DataTypes.sol b/contracts/protocol/libraries/types/DataTypes.sol index a19e5efc..6cf8b913 100644 --- a/contracts/protocol/libraries/types/DataTypes.sol +++ b/contracts/protocol/libraries/types/DataTypes.sol @@ -38,6 +38,7 @@ library DataTypes { //bit 59: stable rate borrowing enabled //bit 60-63: reserved //bit 64-79: reserve factor + //bit 80-95 borrow cap uint256 data; } From a869be648b6050d0834cdba1e714e7b63fa21164 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 26 Apr 2021 09:17:02 +0200 Subject: [PATCH 02/34] refactor: created separate function to get Reserve Borrow cap, so interface for getReserveConfiguration remains identical --- contracts/misc/AaveProtocolDataProvider.sol | 22 ++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/contracts/misc/AaveProtocolDataProvider.sol b/contracts/misc/AaveProtocolDataProvider.sol index 494ee304..78e26b95 100644 --- a/contracts/misc/AaveProtocolDataProvider.sol +++ b/contracts/misc/AaveProtocolDataProvider.sol @@ -73,7 +73,6 @@ contract AaveProtocolDataProvider { uint256 liquidationThreshold, uint256 liquidationBonus, uint256 reserveFactor, - uint256 borrowCap, bool usageAsCollateralEnabled, bool borrowingEnabled, bool stableBorrowRateEnabled, @@ -81,19 +80,28 @@ contract AaveProtocolDataProvider { bool isFrozen ) { + DataTypes.ReserveConfigurationMap memory configuration = + ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getConfiguration(asset); + (ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor, ) = - ILendingPool(ADDRESSES_PROVIDER.getLendingPool()) - .getConfiguration(asset) - .getParamsMemory(); + configuration.getParamsMemory(); (isActive, isFrozen, borrowingEnabled, stableBorrowRateEnabled) = - ILendingPool(ADDRESSES_PROVIDER.getLendingPool()) - .getConfiguration(asset) - .getFlagsMemory(); + configuration.getFlagsMemory(); usageAsCollateralEnabled = liquidationThreshold > 0; } + function getReserveBorrowCap(address asset) + external + view + returns (uint256 borrowCap) { + + (, , , , , borrowCap) = ILendingPool(ADDRESSES_PROVIDER.getLendingPool()) + .getConfiguration(asset) + .getParamsMemory(); + } + function getReserveData(address asset) external view From 03103fb63ddf10efe2a4c7b66da3edf51190f74f Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 27 Apr 2021 18:26:08 +0200 Subject: [PATCH 03/34] adding stack too deep --- contracts/protocol/libraries/helpers/Errors.sol | 1 + .../protocol/libraries/logic/ValidationLogic.sol | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/contracts/protocol/libraries/helpers/Errors.sol b/contracts/protocol/libraries/helpers/Errors.sol index 304f0a33..6ee6cced 100644 --- a/contracts/protocol/libraries/helpers/Errors.sol +++ b/contracts/protocol/libraries/helpers/Errors.sol @@ -103,6 +103,7 @@ library Errors { string public constant LP_NOT_CONTRACT = '78'; string public constant SDT_STABLE_DEBT_OVERFLOW = '79'; string public constant SDT_BURN_EXCEEDS_BALANCE = '80'; + string public constant VL_BORROW_CAP_EXCEEDED = '81'; string public constant RC_INVALID_BORROW_CAP = '82'; enum CollateralManagerErrors { diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index 080b792d..564759c3 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -14,6 +14,8 @@ import {UserConfiguration} from '../configuration/UserConfiguration.sol'; import {Errors} from '../helpers/Errors.sol'; import {Helpers} from '../helpers/Helpers.sol'; import {IReserveInterestRateStrategy} from '../../../interfaces/IReserveInterestRateStrategy.sol'; +import {IVariableDebtToken} from '../../../interfaces/IVariableDebtToken.sol'; +import {IStableDebtToken} from '../../../interfaces/IStableDebtToken.sol'; import {DataTypes} from '../types/DataTypes.sol'; /** @@ -149,6 +151,20 @@ library ValidationLogic { uint256(DataTypes.InterestRateMode.STABLE) == interestRateMode, Errors.VL_INVALID_INTEREST_RATE_MODE_SELECTED ); + + // not using this because stack too deep + // uint256 totalStableDebt; + // (totalStableDebt, ) = IStableDebtToken(reserve.stableDebtTokenAddress) + // .getTotalSupplyAndAvgRate(); + + require( + IERC20(reserve.stableDebtTokenAddress).totalSupply() + .add(IVariableDebtToken(reserve.variableDebtTokenAddress) + .scaledTotalSupply() + .rayMul(reserve.variableBorrowIndex) + ).add(amount) + < reserve.configuration.getBorrowCap(), + Errors.VL_BORROW_CAP_EXCEEDED); ( vars.userCollateralBalanceETH, From 7e02877966dba54d6ed65614dbdf5111341a00e7 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 27 Apr 2021 18:37:13 +0200 Subject: [PATCH 04/34] refactor: fixed stack too deep --- .../libraries/logic/ValidationLogic.sol | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index 564759c3..2f713b12 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -98,6 +98,8 @@ library ValidationLogic { uint256 userBorrowBalanceETH; uint256 availableLiquidity; uint256 healthFactor; + uint256 totalSupplyStableDebt; + uint256 totalSupplyVariableDebt; bool isActive; bool isFrozen; bool borrowingEnabled; @@ -152,17 +154,18 @@ library ValidationLogic { Errors.VL_INVALID_INTEREST_RATE_MODE_SELECTED ); - // not using this because stack too deep - // uint256 totalStableDebt; - // (totalStableDebt, ) = IStableDebtToken(reserve.stableDebtTokenAddress) - // .getTotalSupplyAndAvgRate(); + (vars.totalSupplyStableDebt, ) = IStableDebtToken(reserve.stableDebtTokenAddress) + .getTotalSupplyAndAvgRate(); + + vars.totalSupplyVariableDebt = IVariableDebtToken(reserve.variableDebtTokenAddress) + .scaledTotalSupply() + .rayMul(reserve.variableBorrowIndex); + require( - IERC20(reserve.stableDebtTokenAddress).totalSupply() - .add(IVariableDebtToken(reserve.variableDebtTokenAddress) - .scaledTotalSupply() - .rayMul(reserve.variableBorrowIndex) - ).add(amount) + vars.totalSupplyStableDebt + .add(vars.totalSupplyVariableDebt) + .add(amount) < reserve.configuration.getBorrowCap(), Errors.VL_BORROW_CAP_EXCEEDED); From 05ca0c4ed1d4b5a2b2b544e5debfb68ff39d921f Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 27 Apr 2021 18:43:55 +0200 Subject: [PATCH 05/34] fix: Addded decimals in borrowCap require --- contracts/protocol/libraries/logic/ValidationLogic.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index 2f713b12..bb697fe6 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -166,6 +166,7 @@ library ValidationLogic { vars.totalSupplyStableDebt .add(vars.totalSupplyVariableDebt) .add(amount) + .div(10 ** reserve.configuration.getDecimals()) < reserve.configuration.getBorrowCap(), Errors.VL_BORROW_CAP_EXCEEDED); From 9a8eb294a0f1f21376e39b357e0ef192bedccaf4 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 27 Apr 2021 19:04:29 +0200 Subject: [PATCH 06/34] fix: borrowCap from 16 to 32 bits --- .../protocol/libraries/configuration/ReserveConfiguration.sol | 4 ++-- contracts/protocol/libraries/types/DataTypes.sol | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol index 188bee66..e7ab9da9 100644 --- a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol @@ -19,7 +19,7 @@ library ReserveConfiguration { uint256 constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore - uint256 constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFFFFFF; // 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 +37,7 @@ library ReserveConfiguration { uint256 constant MAX_VALID_LIQUIDATION_BONUS = 65535; uint256 constant MAX_VALID_DECIMALS = 255; uint256 constant MAX_VALID_RESERVE_FACTOR = 65535; - uint256 constant MAX_VALID_BORROW_CAP = 65535; + uint256 constant MAX_VALID_BORROW_CAP = 4294967296; /** * @dev Sets the Loan to Value of the reserve diff --git a/contracts/protocol/libraries/types/DataTypes.sol b/contracts/protocol/libraries/types/DataTypes.sol index 6cf8b913..93ad017d 100644 --- a/contracts/protocol/libraries/types/DataTypes.sol +++ b/contracts/protocol/libraries/types/DataTypes.sol @@ -38,7 +38,7 @@ library DataTypes { //bit 59: stable rate borrowing enabled //bit 60-63: reserved //bit 64-79: reserve factor - //bit 80-95 borrow cap + //bit 80-111 borrow cap uint256 data; } From 6054fa0bd502f22e71b7c9980c0e775bb605974b Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 27 Apr 2021 19:08:49 +0200 Subject: [PATCH 07/34] feat: Added borrowCap to enableBorrowing Configurato --- contracts/deployments/ATokensAndRatesHelper.sol | 2 ++ contracts/protocol/lendingpool/LendingPoolConfigurator.sol | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/deployments/ATokensAndRatesHelper.sol b/contracts/deployments/ATokensAndRatesHelper.sol index 400f7ca6..ee8f6697 100644 --- a/contracts/deployments/ATokensAndRatesHelper.sol +++ b/contracts/deployments/ATokensAndRatesHelper.sol @@ -31,6 +31,7 @@ contract ATokensAndRatesHelper is Ownable { uint256 liquidationThreshold; uint256 liquidationBonus; uint256 reserveFactor; + uint256 borrowCap; bool stableBorrowingEnabled; } @@ -75,6 +76,7 @@ contract ATokensAndRatesHelper is Ownable { configurator.enableBorrowingOnReserve( inputParams[i].asset, + inputParams[i].borrowCap, inputParams[i].stableBorrowingEnabled ); configurator.setReserveFactor(inputParams[i].asset, inputParams[i].reserveFactor); diff --git a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol index ec35b180..99c46976 100644 --- a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol @@ -248,13 +248,14 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur * @param asset The address of the underlying asset of the reserve * @param stableBorrowRateEnabled True if stable borrow rate needs to be enabled by default on this reserve **/ - function enableBorrowingOnReserve(address asset, bool stableBorrowRateEnabled) + function enableBorrowingOnReserve(address asset, uint256 borrowCap, bool stableBorrowRateEnabled) external onlyPoolAdmin { DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); currentConfig.setBorrowingEnabled(true); + currentConfig.setBorrowCap(borrowCap); currentConfig.setStableRateBorrowingEnabled(stableBorrowRateEnabled); pool.setConfiguration(asset, currentConfig.data); From 32cfe739c702b9d784006fc3b75d634e86520ef4 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Wed, 28 Apr 2021 17:42:41 +0200 Subject: [PATCH 08/34] fix-test: fixed max Borrow Cap, adapted test asset init, asset config --- .../configuration/ReserveConfiguration.sol | 2 +- helpers/constants.ts | 1 + helpers/init-helpers.ts | 12 +++- helpers/types.ts | 1 + markets/aave/reservesConfigs.ts | 62 +++++++++++++------ test-suites/test-aave/configurator.spec.ts | 8 ++- test-suites/test-amm/configurator.spec.ts | 6 +- 7 files changed, 62 insertions(+), 30 deletions(-) diff --git a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol index e7ab9da9..dafd9339 100644 --- a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol @@ -37,7 +37,7 @@ library ReserveConfiguration { uint256 constant MAX_VALID_LIQUIDATION_BONUS = 65535; uint256 constant MAX_VALID_DECIMALS = 255; uint256 constant MAX_VALID_RESERVE_FACTOR = 65535; - uint256 constant MAX_VALID_BORROW_CAP = 4294967296; + uint256 constant MAX_VALID_BORROW_CAP = 4294967295; /** * @dev Sets the Loan to Value of the reserve diff --git a/helpers/constants.ts b/helpers/constants.ts index 95e8922b..56a3e8bf 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -15,6 +15,7 @@ export const oneEther = new BigNumber(Math.pow(10, 18)); export const oneRay = new BigNumber(Math.pow(10, 27)); export const MAX_UINT_AMOUNT = '115792089237316195423570985008687907853269984665640564039457584007913129639935'; +export const MAX_BORROW_CAP = '4294967295'; 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 eb483420..272ee9cc 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -275,6 +275,7 @@ export const configureReservesByHelper = async ( const liquidationThresholds: string[] = []; const liquidationBonuses: string[] = []; const reserveFactors: string[] = []; + const borrowCaps: string[] = []; const stableRatesEnabled: boolean[] = []; const inputParams: { @@ -283,6 +284,7 @@ export const configureReservesByHelper = async ( liquidationThreshold: BigNumberish; liquidationBonus: BigNumberish; reserveFactor: BigNumberish; + borrowCap: BigNumberish; stableBorrowingEnabled: boolean; }[] = []; @@ -293,6 +295,7 @@ export const configureReservesByHelper = async ( liquidationBonus, liquidationThreshold, reserveFactor, + borrowCap, stableBorrowRateEnabled, }, ] of Object.entries(reservesParams) as [string, IReserveParams][]) { @@ -317,9 +320,10 @@ export const configureReservesByHelper = async ( inputParams.push({ asset: tokenAddress, baseLTV: baseLTVAsCollateral, - liquidationThreshold: liquidationThreshold, - liquidationBonus: liquidationBonus, - reserveFactor: reserveFactor, + liquidationThreshold, + liquidationBonus, + reserveFactor, + borrowCap, stableBorrowingEnabled: stableBorrowRateEnabled, }); @@ -329,6 +333,7 @@ export const configureReservesByHelper = async ( liquidationThresholds.push(liquidationThreshold); liquidationBonuses.push(liquidationBonus); reserveFactors.push(reserveFactor); + borrowCaps.push(borrowCap); stableRatesEnabled.push(stableBorrowRateEnabled); } if (tokens.length) { @@ -342,6 +347,7 @@ export const configureReservesByHelper = async ( console.log(`- Configure reserves in ${chunkedInputParams.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedInputParams.length; chunkIndex++) { + console.log('chunk ', chunkedInputParams[chunkIndex]); await waitForTx( await atokenAndRatesDeployer.configureReserves(chunkedInputParams[chunkIndex], { gasLimit: 12000000, diff --git a/helpers/types.ts b/helpers/types.ts index ea8826a0..c6796323 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -386,6 +386,7 @@ export interface IReserveCollateralParams { baseLTVAsCollateral: string; liquidationThreshold: string; liquidationBonus: string; + borrowCap: string; } export interface IMarketRates { borrowRate: string; diff --git a/markets/aave/reservesConfigs.ts b/markets/aave/reservesConfigs.ts index a29e16d7..6f33a99d 100644 --- a/markets/aave/reservesConfigs.ts +++ b/markets/aave/reservesConfigs.ts @@ -1,3 +1,4 @@ +import { MAX_BORROW_CAP } from '../../helpers/constants'; import { eContractid, IReserveParams } from '../../helpers/types'; import { @@ -21,7 +22,8 @@ export const strategyBUSD: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyDAI: IReserveParams = { @@ -33,7 +35,8 @@ export const strategyDAI: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategySUSD: IReserveParams = { @@ -45,7 +48,8 @@ export const strategySUSD: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyTUSD: IReserveParams = { @@ -57,7 +61,8 @@ export const strategyTUSD: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyUSDC: IReserveParams = { @@ -69,7 +74,8 @@ export const strategyUSDC: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '6', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyUSDT: IReserveParams = { @@ -81,7 +87,8 @@ export const strategyUSDT: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '6', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyAAVE: IReserveParams = { @@ -93,7 +100,8 @@ export const strategyAAVE: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '0', + borrowCap: MAX_BORROW_CAP, }; export const strategyBAT: IReserveParams = { @@ -105,7 +113,8 @@ export const strategyBAT: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyENJ: IReserveParams = { @@ -117,7 +126,8 @@ export const strategyENJ: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyWETH: IReserveParams = { @@ -129,7 +139,8 @@ export const strategyWETH: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyKNC: IReserveParams = { @@ -141,7 +152,8 @@ export const strategyKNC: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyLINK: IReserveParams = { @@ -153,7 +165,8 @@ export const strategyLINK: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyMANA: IReserveParams = { @@ -165,7 +178,8 @@ export const strategyMANA: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '3500' + reserveFactor: '3500', + borrowCap: MAX_BORROW_CAP, }; export const strategyMKR: IReserveParams = { @@ -177,7 +191,8 @@ export const strategyMKR: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyREN: IReserveParams = { @@ -189,7 +204,8 @@ export const strategyREN: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategySNX: IReserveParams = { @@ -201,7 +217,8 @@ export const strategySNX: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '3500' + reserveFactor: '3500', + borrowCap: MAX_BORROW_CAP, }; // Invalid borrow rates in params currently, replaced with snx params @@ -214,7 +231,8 @@ export const strategyUNI: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.DelegationAwareAToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyWBTC: IReserveParams = { @@ -226,7 +244,8 @@ export const strategyWBTC: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '8', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyYFI: IReserveParams = { @@ -238,7 +257,8 @@ export const strategyYFI: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyZRX: IReserveParams = { @@ -250,7 +270,8 @@ export const strategyZRX: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyXSUSHI: IReserveParams = { @@ -263,4 +284,5 @@ export const strategyXSUSHI: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '3500', + borrowCap: MAX_BORROW_CAP, }; \ No newline at end of file diff --git a/test-suites/test-aave/configurator.spec.ts b/test-suites/test-aave/configurator.spec.ts index c94dcdf8..57440406 100644 --- a/test-suites/test-aave/configurator.spec.ts +++ b/test-suites/test-aave/configurator.spec.ts @@ -1,5 +1,5 @@ import { TestEnv, makeSuite } from './helpers/make-suite'; -import { APPROVAL_AMOUNT_LENDING_POOL, RAY } from '../../helpers/constants'; +import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, RAY, MAX_BORROW_CAP } from '../../helpers/constants'; import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; import { ProtocolErrors } from '../../helpers/types'; import { strategyWETH } from '../../markets/aave/reservesConfigs'; @@ -156,7 +156,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { it('Activates the ETH reserve for borrowing', async () => { const { configurator, weth, helpersContract } = testEnv; - await configurator.enableBorrowingOnReserve(weth.address, true); + await configurator.enableBorrowingOnReserve(weth.address, MAX_BORROW_CAP, true); const { variableBorrowIndex } = await helpersContract.getReserveData(weth.address); const { @@ -195,7 +195,9 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => { const { configurator, users, weth } = testEnv; await expect( - configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, true), + configurator + .connect(users[2].signer) + .enableBorrowingOnReserve(weth.address, MAX_BORROW_CAP, true), CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); diff --git a/test-suites/test-amm/configurator.spec.ts b/test-suites/test-amm/configurator.spec.ts index e4e3f4fa..4884d070 100644 --- a/test-suites/test-amm/configurator.spec.ts +++ b/test-suites/test-amm/configurator.spec.ts @@ -1,5 +1,5 @@ import { TestEnv, makeSuite } from './helpers/make-suite'; -import { APPROVAL_AMOUNT_LENDING_POOL, RAY } from '../../helpers/constants'; +import { APPROVAL_AMOUNT_LENDING_POOL, MAX_BORROW_CAP, RAY } from '../../helpers/constants'; import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; import { ProtocolErrors } from '../../helpers/types'; import { strategyWETH } from '../../markets/amm/reservesConfigs'; @@ -156,7 +156,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { it('Activates the ETH reserve for borrowing', async () => { const { configurator, weth, helpersContract } = testEnv; - await configurator.enableBorrowingOnReserve(weth.address, true); + await configurator.enableBorrowingOnReserve(weth.address, MAX_BORROW_CAP, true); const { variableBorrowIndex } = await helpersContract.getReserveData(weth.address); const { @@ -195,7 +195,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => { const { configurator, users, weth } = testEnv; await expect( - configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, true), + configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, MAX_BORROW_CAP, true), CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); From a9fce4dd4b25226df1c5f6d6c738f8ecc6a99e7e Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Thu, 29 Apr 2021 09:51:37 +0200 Subject: [PATCH 09/34] feat: Added setBorrowCap in lendingpoolconfigurator --- contracts/interfaces/ILendingPoolConfigurator.sol | 7 +++++++ .../lendingpool/LendingPoolConfigurator.sol | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/contracts/interfaces/ILendingPoolConfigurator.sol b/contracts/interfaces/ILendingPoolConfigurator.sol index 7554f2a8..2dcd8259 100644 --- a/contracts/interfaces/ILendingPoolConfigurator.sol +++ b/contracts/interfaces/ILendingPoolConfigurator.sol @@ -127,6 +127,13 @@ interface ILendingPoolConfigurator { **/ event ReserveFactorChanged(address indexed asset, uint256 factor); + /** + * @dev Emitted when the borrow cap of a reserve is updated + * @param asset The address of the underlying asset of the reserve + * @param borrowCap The new borrow cap + **/ + event BorrowCapChanged(address indexed asset, uint256 borrowCap); + /** * @dev Emitted when the reserve decimals are updated * @param asset The address of the underlying asset of the reserve diff --git a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol index 99c46976..66100e1e 100644 --- a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol @@ -431,6 +431,21 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur emit ReserveFactorChanged(asset, reserveFactor); } + /** + * @dev Updates the borrow cap of a reserve + * @param asset The address of the underlying asset of the reserve + * @param borrowCap The new borrow of the reserve + **/ + function setBorrowCap(address asset, uint256 borrowCap) external onlyPoolAdmin { + DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + + currentConfig.setBorrowCap(borrowCap); + + pool.setConfiguration(asset, currentConfig.data); + + emit BorrowCapChanged(asset, borrowCap); + } + /** * @dev Sets the interest rate strategy of a reserve * @param asset The address of the underlying asset of the reserve From be4fc154baa70df53bb0066940019a303a448f20 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Thu, 29 Apr 2021 10:16:12 +0200 Subject: [PATCH 10/34] config: added borrowCap config to matic, amm markets, all default to max borrow cap --- markets/amm/reservesConfigs.ts | 61 +++++++++++++++++++++----------- markets/matic/reservesConfigs.ts | 19 ++++++---- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/markets/amm/reservesConfigs.ts b/markets/amm/reservesConfigs.ts index c92aa42f..c443953b 100644 --- a/markets/amm/reservesConfigs.ts +++ b/markets/amm/reservesConfigs.ts @@ -1,3 +1,4 @@ +import { MAX_BORROW_CAP } from '../../helpers/constants'; import { eContractid, IReserveParams} from '../../helpers/types'; import { rateStrategyAmmBase, @@ -15,7 +16,8 @@ export const strategyWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyWBTC: IReserveParams = { @@ -27,7 +29,8 @@ export const strategyWBTC: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '8', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyDAI: IReserveParams = { @@ -39,7 +42,8 @@ export const strategyDAI: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyUSDC: IReserveParams = { @@ -51,7 +55,8 @@ export const strategyUSDC: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '6', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyUSDT: IReserveParams = { @@ -63,7 +68,8 @@ export const strategyUSDT: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '6', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyDAIWETH: IReserveParams = { @@ -75,7 +81,8 @@ export const strategyDAIWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyWBTCWETH: IReserveParams = { @@ -87,7 +94,8 @@ export const strategyWBTCWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: MAX_BORROW_CAP, }; export const strategyAAVEWETH: IReserveParams = { @@ -99,7 +107,8 @@ export const strategyAAVEWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '500' + reserveFactor: '500', + borrowCap: MAX_BORROW_CAP, }; export const strategyBATWETH: IReserveParams = { @@ -111,7 +120,8 @@ export const strategyBATWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: MAX_BORROW_CAP, }; export const strategyDAIUSDC: IReserveParams = { @@ -123,7 +133,8 @@ export const strategyDAIUSDC: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyCRVWETH: IReserveParams = { @@ -135,7 +146,8 @@ export const strategyCRVWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: MAX_BORROW_CAP, }; export const strategyLINKWETH: IReserveParams = { @@ -147,7 +159,8 @@ export const strategyLINKWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: MAX_BORROW_CAP, }; export const strategyMKRWETH: IReserveParams = { @@ -159,7 +172,8 @@ export const strategyMKRWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: MAX_BORROW_CAP, }; export const strategyRENWETH: IReserveParams = { @@ -171,7 +185,8 @@ export const strategyRENWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: MAX_BORROW_CAP, }; export const strategySNXWETH: IReserveParams = { @@ -183,7 +198,8 @@ export const strategySNXWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyUNIWETH: IReserveParams = { @@ -195,7 +211,8 @@ export const strategyUNIWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: MAX_BORROW_CAP, }; export const strategyUSDCWETH: IReserveParams = { @@ -207,7 +224,8 @@ export const strategyUSDCWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyWBTCUSDC: IReserveParams = { @@ -219,7 +237,8 @@ export const strategyWBTCUSDC: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: MAX_BORROW_CAP, }; export const strategyYFIWETH: IReserveParams = { @@ -231,7 +250,8 @@ export const strategyYFIWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: MAX_BORROW_CAP, }; export const strategyBALWETH: IReserveParams = { @@ -243,5 +263,6 @@ export const strategyBALWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: MAX_BORROW_CAP, } \ No newline at end of file diff --git a/markets/matic/reservesConfigs.ts b/markets/matic/reservesConfigs.ts index 608d028b..66acf51e 100644 --- a/markets/matic/reservesConfigs.ts +++ b/markets/matic/reservesConfigs.ts @@ -1,5 +1,6 @@ // import BigNumber from 'bignumber.js'; // import { oneRay } from '../../helpers/constants'; +import { MAX_BORROW_CAP } from '../../helpers/constants'; import { eContractid, IReserveParams } from '../../helpers/types'; import { rateStrategyStableOne, @@ -21,7 +22,8 @@ export const strategyDAI: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyUSDC: IReserveParams = { @@ -33,7 +35,8 @@ export const strategyUSDC: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '6', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyUSDT: IReserveParams = { @@ -45,7 +48,8 @@ export const strategyUSDT: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '6', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyWETH: IReserveParams = { @@ -57,7 +61,8 @@ export const strategyWETH: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, }; export const strategyWBTC: IReserveParams = { @@ -69,7 +74,8 @@ export const strategyWBTC: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '8', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; export const strategyMATIC: IReserveParams = { @@ -81,5 +87,6 @@ export const strategyMATIC: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: MAX_BORROW_CAP, }; \ No newline at end of file From 01e23fffc89c7ad2edca3dd9d53733731e5a50f5 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Thu, 29 Apr 2021 10:16:29 +0200 Subject: [PATCH 11/34] test: updated test to check borrowCap --- test-suites/test-aave/configurator.spec.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test-suites/test-aave/configurator.spec.ts b/test-suites/test-aave/configurator.spec.ts index 57440406..b740aabd 100644 --- a/test-suites/test-aave/configurator.spec.ts +++ b/test-suites/test-aave/configurator.spec.ts @@ -73,6 +73,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -83,6 +84,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); }); it('Unfreezes the ETH reserve', async () => { @@ -100,6 +102,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -110,6 +113,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); }); it('Check the onlyAaveAdmin on freezeReserve ', async () => { @@ -142,6 +146,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); expect(borrowingEnabled).to.be.equal(false); expect(isActive).to.be.equal(true); @@ -152,6 +157,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); }); it('Activates the ETH reserve for borrowing', async () => { @@ -170,6 +176,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -180,6 +187,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(variableBorrowIndex.toString()).to.be.equal(RAY); }); @@ -217,6 +225,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -227,6 +236,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(0); expect(stableBorrowRateEnabled).to.be.equal(true); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); }); it('Activates the ETH reserve as collateral', async () => { @@ -244,6 +254,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -254,6 +265,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); }); it('Check the onlyAaveAdmin on configureReserveAsCollateral ', async () => { @@ -280,6 +292,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -290,6 +303,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(false); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); }); it('Enables stable borrow rate on the ETH reserve', async () => { @@ -306,6 +320,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -316,6 +331,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(true); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); }); it('Check the onlyAaveAdmin on disableReserveStableRate', async () => { @@ -348,6 +364,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); From 9c02b5d79b186c116b1c51180dca03c1b38cb8cb Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Thu, 29 Apr 2021 10:34:00 +0200 Subject: [PATCH 12/34] test: finish tested configurator part of borrowCap --- helpers/types.ts | 2 + test-suites/test-aave/configurator.spec.ts | 52 ++++++++++++++++++++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/helpers/types.ts b/helpers/types.ts index c6796323..dd8cec9e 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -178,6 +178,8 @@ export enum ProtocolErrors { RC_INVALID_DECIMALS = '70', RC_INVALID_RESERVE_FACTOR = '71', LPAPR_INVALID_ADDRESSES_PROVIDER_ID = '72', + VL_BORROW_CAP_EXCEEDED = '81', + RC_INVALID_BORROW_CAP = '82', // old diff --git a/test-suites/test-aave/configurator.spec.ts b/test-suites/test-aave/configurator.spec.ts index b740aabd..3ef4d4f8 100644 --- a/test-suites/test-aave/configurator.spec.ts +++ b/test-suites/test-aave/configurator.spec.ts @@ -15,6 +15,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { RC_INVALID_LIQ_BONUS, RC_INVALID_DECIMALS, RC_INVALID_RESERVE_FACTOR, + RC_INVALID_BORROW_CAP, } = ProtocolErrors; it('Reverts trying to set an invalid reserve factor', async () => { @@ -350,6 +351,22 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); + it('Check the onlyAaveAdmin on setReserveFactor', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).setReserveFactor(weth.address, '1000'), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + + it('Check the onlyAaveAdmin on setBorrowCap', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).setBorrowCap(weth.address, '3000000000'), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); + it('Changes the reserve factor of WETH', async () => { const { configurator, helpersContract, weth } = testEnv; await configurator.setReserveFactor(weth.address, '1000'); @@ -374,15 +391,44 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); expect(reserveFactor).to.be.equal(1000); }); - it('Check the onlyLendingPoolManager on setReserveFactor', async () => { + it('Fails to change to too high borrowCap', async () => { const { configurator, users, weth } = testEnv; await expect( - configurator.connect(users[2].signer).setReserveFactor(weth.address, '2000'), + configurator.setBorrowCap(weth.address, '4294967296'), CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + ).to.be.revertedWith(RC_INVALID_BORROW_CAP); + }); + + it('Changes the borrow Cap of WETH', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.setBorrowCap(weth.address, '3000000'); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + 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'); }); it('Reverts when trying to disable the DAI reserve with liquidity on it', async () => { From be1181e26fcbd7cd193d2799ff52c6afe5a8aecb Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Thu, 29 Apr 2021 13:51:45 +0200 Subject: [PATCH 13/34] flex: added contributor --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 4532f6fa..2a739f22 100644 --- a/package.json +++ b/package.json @@ -140,7 +140,8 @@ "Andrey Kozlov ", "David Racero ", "Pol Sendra ", - "David Truong " + "David Truong ", + "Hadrien Charlanes " ], "license": "AGPLv3", "dependencies": { From 41c53842f76707a54cbb1f562f987c5e09090065 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Thu, 29 Apr 2021 18:11:57 +0200 Subject: [PATCH 14/34] test: added tests for borrow cap --- package.json | 1 + test-suites/test-aave/borrow-cap.spec.ts | 236 +++++++++++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 test-suites/test-aave/borrow-cap.spec.ts diff --git a/package.json b/package.json index 2a739f22..eb49517b 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "test-liquidate-with-collateral": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/flash-liquidation-with-collateral.spec.ts", "test-liquidate-underlying": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/liquidation-underlying.spec.ts", "test-configurator": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/configurator.spec.ts", + "test-borrow-cap": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/borrow-cap.spec.ts", "test-transfers": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-transfer.spec.ts", "test-flash": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/flashloan.spec.ts", "test-liquidate": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/liquidation-atoken.spec.ts", diff --git a/test-suites/test-aave/borrow-cap.spec.ts b/test-suites/test-aave/borrow-cap.spec.ts new file mode 100644 index 00000000..dfd0fa40 --- /dev/null +++ b/test-suites/test-aave/borrow-cap.spec.ts @@ -0,0 +1,236 @@ +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { + APPROVAL_AMOUNT_LENDING_POOL, + MAX_UINT_AMOUNT, + RAY, + MAX_BORROW_CAP, +} from '../../helpers/constants'; +import { ProtocolErrors } from '../../helpers/types'; +import { MintableERC20, WETH9, WETH9Mocked } from '../../types'; +import { parseEther } from '@ethersproject/units'; +import { BigNumber } from '@ethersproject/bignumber'; + +const { expect } = require('chai'); + +makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { + const { VL_BORROW_CAP_EXCEEDED } = ProtocolErrors; + + const miliUnitToPrecision = async (token: WETH9Mocked | MintableERC20, nb: string) => + BigNumber.from(nb).mul(BigNumber.from('10').pow((await token.decimals()) - 3)); + + it('Sets the borrow cap for Weth and DAI to 0 Units, deposits weth', async () => { + const { + configurator, + weth, + pool, + dai, + usdc, + deployer, + helpersContract, + users: [user1], + } = testEnv; + const mintedAmount = parseEther('1000000000'); + await dai.mint(mintedAmount); + await weth.mint(mintedAmount); + await usdc.mint(mintedAmount); + 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); + let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); + let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + + expect(usdcBorrowCap).to.be.equal(MAX_BORROW_CAP); + expect(daiBorrowCap).to.be.equal(MAX_BORROW_CAP); + + const depositedMiliAmount = (1e9).toString(); + + await configurator.setBorrowCap(usdc.address, 0); + await configurator.setBorrowCap(dai.address, 0); + + usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); + daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + + expect(usdcBorrowCap).to.be.equal(0); + expect(daiBorrowCap).to.be.equal(0); + + await pool.deposit( + weth.address, + await miliUnitToPrecision(weth, depositedMiliAmount), + deployer.address, + 0 + ); + await pool.connect(user1.signer).deposit(weth.address, mintedAmount, user1.address, 0); + await pool.connect(user1.signer).deposit(dai.address, mintedAmount, user1.address, 0); + await pool.connect(user1.signer).deposit(usdc.address, mintedAmount, user1.address, 0); + }); + it('should fail to borrow any dai or usdc, stable or variable', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 10; + const borrowedMilimount = (borrowedAmount * 1000).toString(); + + await expect( + pool.borrow( + usdc.address, + await miliUnitToPrecision(usdc, borrowedMilimount), + 2, + 0, + deployer.address + ) + ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); + + await expect( + pool.borrow( + dai.address, + await miliUnitToPrecision(dai, borrowedMilimount), + 2, + 0, + deployer.address + ) + ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); + }); + it('Sets the borrow cap for usdc and DAI to 100 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = '100'; + let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); + let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + + expect(usdcBorrowCap).to.be.equal(0); + expect(daiBorrowCap).to.be.equal(0); + + await configurator.setBorrowCap(usdc.address, newCap); + await configurator.setBorrowCap(dai.address, newCap); + + usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); + daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + + expect(usdcBorrowCap).to.be.equal(newCap); + expect(daiBorrowCap).to.be.equal(newCap); + }); + it('should succeed to borrow 10 stable dai and 10 variable usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 10; + const borrowedMilimount = (borrowedAmount * 1000).toString(); + await pool.borrow( + usdc.address, + await miliUnitToPrecision(usdc, borrowedMilimount), + 2, + 0, + deployer.address + ); + + await pool.borrow( + dai.address, + await miliUnitToPrecision(dai, borrowedMilimount), + 1, + 0, + deployer.address + ); + }); + it('should fail to borrow 100 variable dai and 100 stable usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 100; + const borrowedMilimount = (borrowedAmount * 1000).toString(); + + await expect( + pool.borrow( + usdc.address, + await miliUnitToPrecision(usdc, borrowedMilimount), + 1, + 0, + deployer.address + ) + ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); + + await expect( + pool.borrow( + dai.address, + await miliUnitToPrecision(dai, borrowedMilimount), + 2, + 0, + deployer.address + ) + ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); + }); + it('Raises the borrow cap for usdc and DAI to 1000 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = '1000'; + let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); + let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + + await configurator.setBorrowCap(usdc.address, newCap); + await configurator.setBorrowCap(dai.address, newCap); + + usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); + daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + + expect(usdcBorrowCap).to.be.equal(newCap); + expect(daiBorrowCap).to.be.equal(newCap); + }); + it('should succeed to borrow 100 variable dai and 100 stable usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 100; + const borrowedMilimount = (borrowedAmount * 1000).toString(); + + pool.borrow( + usdc.address, + await miliUnitToPrecision(usdc, borrowedMilimount), + 1, + 0, + deployer.address + ); + + pool.borrow( + dai.address, + await miliUnitToPrecision(dai, borrowedMilimount), + 2, + 0, + deployer.address + ); + }); + it('Lowers the borrow cap for usdc and DAI to 200 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = '200'; + let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); + let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + + await configurator.setBorrowCap(usdc.address, newCap); + await configurator.setBorrowCap(dai.address, newCap); + + usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); + daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + + expect(usdcBorrowCap).to.be.equal(newCap); + expect(daiBorrowCap).to.be.equal(newCap); + }); + it('should fail to borrow 100 variable dai and 100 stable usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 100; + const borrowedMilimount = (borrowedAmount * 1000).toString(); + + await expect( + pool.borrow( + usdc.address, + await miliUnitToPrecision(usdc, borrowedMilimount), + 1, + 0, + deployer.address + ) + ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); + + await expect( + pool.borrow( + dai.address, + await miliUnitToPrecision(dai, borrowedMilimount), + 2, + 0, + deployer.address + ) + ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); + }); +}); From c7bf3e861f7f116b8f15966506cc1dd66c939b88 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 30 Apr 2021 09:28:35 +0200 Subject: [PATCH 15/34] fix: updated test name --- test-suites/test-aave/borrow-cap.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test-suites/test-aave/borrow-cap.spec.ts b/test-suites/test-aave/borrow-cap.spec.ts index dfd0fa40..f6c8cd29 100644 --- a/test-suites/test-aave/borrow-cap.spec.ts +++ b/test-suites/test-aave/borrow-cap.spec.ts @@ -12,7 +12,7 @@ import { BigNumber } from '@ethersproject/bignumber'; const { expect } = require('chai'); -makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { +makeSuite('Borrow Cap', (testEnv: TestEnv) => { const { VL_BORROW_CAP_EXCEEDED } = ProtocolErrors; const miliUnitToPrecision = async (token: WETH9Mocked | MintableERC20, nb: string) => @@ -73,6 +73,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const borrowedAmount = 10; const borrowedMilimount = (borrowedAmount * 1000).toString(); + console.log('hihi', await usdc.decimals()); await expect( pool.borrow( From dac8812c3c37850cf6c3a1a2a4f35ecffdfd5954 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 30 Apr 2021 09:36:46 +0200 Subject: [PATCH 16/34] test: testing borrow cap overflow, max borrow cap --- test-suites/test-aave/borrow-cap.spec.ts | 60 ++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/test-suites/test-aave/borrow-cap.spec.ts b/test-suites/test-aave/borrow-cap.spec.ts index f6c8cd29..43dfd314 100644 --- a/test-suites/test-aave/borrow-cap.spec.ts +++ b/test-suites/test-aave/borrow-cap.spec.ts @@ -13,7 +13,7 @@ import { BigNumber } from '@ethersproject/bignumber'; const { expect } = require('chai'); makeSuite('Borrow Cap', (testEnv: TestEnv) => { - const { VL_BORROW_CAP_EXCEEDED } = ProtocolErrors; + const { VL_BORROW_CAP_EXCEEDED, RC_INVALID_BORROW_CAP } = ProtocolErrors; const miliUnitToPrecision = async (token: WETH9Mocked | MintableERC20, nb: string) => BigNumber.from(nb).mul(BigNumber.from('10').pow((await token.decimals()) - 3)); @@ -73,7 +73,6 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const borrowedAmount = 10; const borrowedMilimount = (borrowedAmount * 1000).toString(); - console.log('hihi', await usdc.decimals()); await expect( pool.borrow( @@ -95,6 +94,25 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { ) ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); }); + it('Should fail to set the borrow cap for usdc and DAI to max cap + 1 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = Number(MAX_BORROW_CAP) + 1; + let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); + let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + + expect(usdcBorrowCap).to.be.equal(0); + expect(daiBorrowCap).to.be.equal(0); + + await expect(configurator.setBorrowCap(usdc.address, newCap)).to.be.revertedWith( + RC_INVALID_BORROW_CAP + ); + await expect(configurator.setBorrowCap(dai.address, newCap)).to.be.revertedWith( + RC_INVALID_BORROW_CAP + ); + + usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); + daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + }); it('Sets the borrow cap for usdc and DAI to 100 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; const newCap = '100'; @@ -113,7 +131,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { expect(usdcBorrowCap).to.be.equal(newCap); expect(daiBorrowCap).to.be.equal(newCap); }); - it('should succeed to borrow 10 stable dai and 10 variable usdc', async () => { + it('Should succeed to borrow 10 stable dai and 10 variable usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const borrowedAmount = 10; const borrowedMilimount = (borrowedAmount * 1000).toString(); @@ -234,4 +252,40 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { ) ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); }); + it('Raises the borrow cap for usdc and DAI to max cap Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = MAX_BORROW_CAP; + let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); + let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + + await configurator.setBorrowCap(usdc.address, newCap); + await configurator.setBorrowCap(dai.address, newCap); + + usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); + daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + + expect(usdcBorrowCap).to.be.equal(newCap); + expect(daiBorrowCap).to.be.equal(newCap); + }); + it('should succeed to borrow 100 variable dai and 100 stable usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 100; + const borrowedMilimount = (borrowedAmount * 1000).toString(); + + pool.borrow( + usdc.address, + await miliUnitToPrecision(usdc, borrowedMilimount), + 1, + 0, + deployer.address + ); + + pool.borrow( + dai.address, + await miliUnitToPrecision(dai, borrowedMilimount), + 2, + 0, + deployer.address + ); + }); }); From 08e14b7565b4502e84cd4fac1c1d3045887d20f4 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 30 Apr 2021 11:02:28 +0200 Subject: [PATCH 17/34] test: added more precised cap test --- test-suites/test-aave/borrow-cap.spec.ts | 26 +++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/test-suites/test-aave/borrow-cap.spec.ts b/test-suites/test-aave/borrow-cap.spec.ts index 43dfd314..1d72c8a9 100644 --- a/test-suites/test-aave/borrow-cap.spec.ts +++ b/test-suites/test-aave/borrow-cap.spec.ts @@ -113,9 +113,9 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); }); - it('Sets the borrow cap for usdc and DAI to 100 Units', async () => { + it('Sets the borrow cap for usdc and DAI to 110 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; - const newCap = '100'; + const newCap = '110'; let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); @@ -151,7 +151,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { deployer.address ); }); - it('should fail to borrow 100 variable dai and 100 stable usdc', async () => { + it('should fail to borrow 100 variable dai and 100 stable usdc (interests accrued)', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const borrowedAmount = 100; const borrowedMilimount = (borrowedAmount * 1000).toString(); @@ -176,6 +176,26 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { ) ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); }); + it('Should succeed to borrow 99 variable dai and 99 stable usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 99; + const borrowedMilimount = (borrowedAmount * 1000).toString(); + await pool.borrow( + usdc.address, + await miliUnitToPrecision(usdc, borrowedMilimount), + 2, + 0, + deployer.address + ); + + await pool.borrow( + dai.address, + await miliUnitToPrecision(dai, borrowedMilimount), + 1, + 0, + deployer.address + ); + }); it('Raises the borrow cap for usdc and DAI to 1000 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; const newCap = '1000'; From c907d15e224be50b6153fa76e690b1c345fd8b45 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 30 Apr 2021 12:02:18 +0200 Subject: [PATCH 18/34] feat: borrowCap from 32 bits (4 billion max cap) to 48 bits (280 trilly) --- .../protocol/libraries/configuration/ReserveConfiguration.sol | 4 ++-- contracts/protocol/libraries/types/DataTypes.sol | 2 +- helpers/constants.ts | 2 +- test-suites/test-aave/configurator.spec.ts | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol index dafd9339..51fabbf9 100644 --- a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol @@ -19,7 +19,7 @@ library ReserveConfiguration { uint256 constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore - uint256 constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFF; // 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 +37,7 @@ library ReserveConfiguration { uint256 constant MAX_VALID_LIQUIDATION_BONUS = 65535; uint256 constant MAX_VALID_DECIMALS = 255; uint256 constant MAX_VALID_RESERVE_FACTOR = 65535; - uint256 constant MAX_VALID_BORROW_CAP = 4294967295; + uint256 constant MAX_VALID_BORROW_CAP = 281474976710655; /** * @dev Sets the Loan to Value of the reserve diff --git a/contracts/protocol/libraries/types/DataTypes.sol b/contracts/protocol/libraries/types/DataTypes.sol index 93ad017d..26a041ab 100644 --- a/contracts/protocol/libraries/types/DataTypes.sol +++ b/contracts/protocol/libraries/types/DataTypes.sol @@ -38,7 +38,7 @@ library DataTypes { //bit 59: stable rate borrowing enabled //bit 60-63: reserved //bit 64-79: reserve factor - //bit 80-111 borrow cap + //bit 80-127 borrow cap uint256 data; } diff --git a/helpers/constants.ts b/helpers/constants.ts index 56a3e8bf..47371513 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -15,7 +15,7 @@ export const oneEther = new BigNumber(Math.pow(10, 18)); export const oneRay = new BigNumber(Math.pow(10, 27)); export const MAX_UINT_AMOUNT = '115792089237316195423570985008687907853269984665640564039457584007913129639935'; -export const MAX_BORROW_CAP = '4294967295'; +export const MAX_BORROW_CAP = '281474976710655'; export const ONE_YEAR = '31536000'; export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; export const ONE_ADDRESS = '0x0000000000000000000000000000000000000001'; diff --git a/test-suites/test-aave/configurator.spec.ts b/test-suites/test-aave/configurator.spec.ts index 3ef4d4f8..9a3bfc2f 100644 --- a/test-suites/test-aave/configurator.spec.ts +++ b/test-suites/test-aave/configurator.spec.ts @@ -3,6 +3,7 @@ import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, RAY, MAX_BORROW_CAP } fr import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; import { ProtocolErrors } from '../../helpers/types'; import { strategyWETH } from '../../markets/aave/reservesConfigs'; +import { BigNumber } from '@ethersproject/bignumber'; const { expect } = require('chai'); @@ -398,7 +399,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { it('Fails to change to too high borrowCap', async () => { const { configurator, users, weth } = testEnv; await expect( - configurator.setBorrowCap(weth.address, '4294967296'), + configurator.setBorrowCap(weth.address, BigNumber.from(MAX_BORROW_CAP).add(1)), CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(RC_INVALID_BORROW_CAP); }); From c8ff80b6a35e02391104e0d8a92d4ed8d390e290 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 30 Apr 2021 12:08:09 +0200 Subject: [PATCH 19/34] clean: removed console log --- helpers/init-helpers.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 272ee9cc..65c3a14e 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -347,7 +347,6 @@ export const configureReservesByHelper = async ( console.log(`- Configure reserves in ${chunkedInputParams.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedInputParams.length; chunkIndex++) { - console.log('chunk ', chunkedInputParams[chunkIndex]); await waitForTx( await atokenAndRatesDeployer.configureReserves(chunkedInputParams[chunkIndex], { gasLimit: 12000000, From cd2eb0af58467327cd8b7db9d4d9b4b7cf9cb98b Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 30 Apr 2021 12:14:48 +0200 Subject: [PATCH 20/34] fix: added missing await to tess txs --- test-suites/test-aave/borrow-cap.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test-suites/test-aave/borrow-cap.spec.ts b/test-suites/test-aave/borrow-cap.spec.ts index 1d72c8a9..6b127855 100644 --- a/test-suites/test-aave/borrow-cap.spec.ts +++ b/test-suites/test-aave/borrow-cap.spec.ts @@ -216,7 +216,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { const borrowedAmount = 100; const borrowedMilimount = (borrowedAmount * 1000).toString(); - pool.borrow( + await pool.borrow( usdc.address, await miliUnitToPrecision(usdc, borrowedMilimount), 1, @@ -224,7 +224,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { deployer.address ); - pool.borrow( + await pool.borrow( dai.address, await miliUnitToPrecision(dai, borrowedMilimount), 2, @@ -292,7 +292,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { const borrowedAmount = 100; const borrowedMilimount = (borrowedAmount * 1000).toString(); - pool.borrow( + await pool.borrow( usdc.address, await miliUnitToPrecision(usdc, borrowedMilimount), 1, @@ -300,7 +300,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { deployer.address ); - pool.borrow( + await pool.borrow( dai.address, await miliUnitToPrecision(dai, borrowedMilimount), 2, From f624783a36fae88785646bda8093d3ecdc32bb1f Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 30 Apr 2021 16:14:59 +0200 Subject: [PATCH 21/34] feat-refactor: added supplyCap and refactored borrowCap --- .../deployments/ATokensAndRatesHelper.sol | 2 + .../interfaces/ILendingPoolConfigurator.sol | 7 ++ contracts/misc/AaveProtocolDataProvider.sol | 11 +-- contracts/misc/UiPoolDataProvider.sol | 7 +- .../misc/interfaces/IUiPoolDataProvider.sol | 1 + .../LendingPoolCollateralManager.sol | 2 +- .../lendingpool/LendingPoolConfigurator.sol | 21 ++++- .../configuration/ReserveConfiguration.sol | 84 +++++++++++++++++-- .../protocol/libraries/helpers/Errors.sol | 2 + .../protocol/libraries/logic/GenericLogic.sol | 4 +- test-suites/test-amm/configurator.spec.ts | 8 +- 11 files changed, 125 insertions(+), 24 deletions(-) diff --git a/contracts/deployments/ATokensAndRatesHelper.sol b/contracts/deployments/ATokensAndRatesHelper.sol index ee8f6697..2240a514 100644 --- a/contracts/deployments/ATokensAndRatesHelper.sol +++ b/contracts/deployments/ATokensAndRatesHelper.sol @@ -32,6 +32,7 @@ contract ATokensAndRatesHelper is Ownable { uint256 liquidationBonus; uint256 reserveFactor; uint256 borrowCap; + uint256 supplyCap; bool stableBorrowingEnabled; } @@ -79,6 +80,7 @@ contract ATokensAndRatesHelper is Ownable { inputParams[i].borrowCap, inputParams[i].stableBorrowingEnabled ); + configurator.setSupplyCap(inputParams[i].asset, inputParams[i].supplyCap); configurator.setReserveFactor(inputParams[i].asset, inputParams[i].reserveFactor); } } diff --git a/contracts/interfaces/ILendingPoolConfigurator.sol b/contracts/interfaces/ILendingPoolConfigurator.sol index 2dcd8259..fea5560c 100644 --- a/contracts/interfaces/ILendingPoolConfigurator.sol +++ b/contracts/interfaces/ILendingPoolConfigurator.sol @@ -134,6 +134,13 @@ interface ILendingPoolConfigurator { **/ event BorrowCapChanged(address indexed asset, uint256 borrowCap); + /** + * @dev Emitted when the supply cap of a reserve is updated + * @param asset The address of the underlying asset of the reserve + * @param supplyCap The new supply cap + **/ + event SupplyCapChanged(address indexed asset, uint256 supplyCap); + /** * @dev Emitted when the reserve decimals are updated * @param asset The address of the underlying asset of the reserve diff --git a/contracts/misc/AaveProtocolDataProvider.sol b/contracts/misc/AaveProtocolDataProvider.sol index 78e26b95..d07a5f1b 100644 --- a/contracts/misc/AaveProtocolDataProvider.sol +++ b/contracts/misc/AaveProtocolDataProvider.sol @@ -64,6 +64,7 @@ contract AaveProtocolDataProvider { return aTokens; } + // not returning borrow and supply caps for compatibility function getReserveConfigurationData(address asset) external view @@ -83,7 +84,7 @@ contract AaveProtocolDataProvider { DataTypes.ReserveConfigurationMap memory configuration = ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getConfiguration(asset); - (ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor, ) = + (ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor) = configuration.getParamsMemory(); (isActive, isFrozen, borrowingEnabled, stableBorrowRateEnabled) = @@ -92,14 +93,14 @@ contract AaveProtocolDataProvider { usageAsCollateralEnabled = liquidationThreshold > 0; } - function getReserveBorrowCap(address asset) + function getReserveCaps(address asset) external view - returns (uint256 borrowCap) { + returns (uint256 borrowCap, uint256 supplyCap) { - (, , , , , borrowCap) = ILendingPool(ADDRESSES_PROVIDER.getLendingPool()) + (borrowCap, supplyCap) = ILendingPool(ADDRESSES_PROVIDER.getLendingPool()) .getConfiguration(asset) - .getParamsMemory(); + .getCapsMemory(); } function getReserveData(address asset) diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index b59da60f..9643385a 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -104,9 +104,12 @@ contract UiPoolDataProvider is IUiPoolDataProvider { reserveData.reserveLiquidationThreshold, reserveData.reserveLiquidationBonus, reserveData.decimals, - reserveData.reserveFactor, - reserveData.borrowCap + reserveData.reserveFactor ) = baseData.configuration.getParamsMemory(); + ( + reserveData.borrowCap, + reserveData.supplyCap + ) = baseData.configuration.getCapsMemory(); ( reserveData.isActive, reserveData.isFrozen, diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index a93c0a43..06979a14 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -15,6 +15,7 @@ interface IUiPoolDataProvider { uint256 reserveLiquidationBonus; uint256 reserveFactor; uint256 borrowCap; + uint256 supplyCap; bool usageAsCollateralEnabled; bool borrowingEnabled; bool stableBorrowRateEnabled; diff --git a/contracts/protocol/lendingpool/LendingPoolCollateralManager.sol b/contracts/protocol/lendingpool/LendingPoolCollateralManager.sol index 53e8fc52..80692726 100644 --- a/contracts/protocol/lendingpool/LendingPoolCollateralManager.sol +++ b/contracts/protocol/lendingpool/LendingPoolCollateralManager.sol @@ -286,7 +286,7 @@ contract LendingPoolCollateralManager is vars.collateralPrice = oracle.getAssetPrice(collateralAsset); vars.debtAssetPrice = oracle.getAssetPrice(debtAsset); - (, , vars.liquidationBonus, vars.collateralDecimals, , ) = collateralReserve + (, , vars.liquidationBonus, vars.collateralDecimals, ) = collateralReserve .configuration .getParams(); vars.debtAssetDecimals = debtReserve.configuration.getDecimals(); diff --git a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol index 66100e1e..85cd32cf 100644 --- a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol @@ -149,7 +149,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); - (, , , uint256 decimals, , ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); + (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); bytes memory encodedCall = abi.encodeWithSelector( IInitializableAToken.initialize.selector, @@ -180,7 +180,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); - (, , , uint256 decimals, , ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); + (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); bytes memory encodedCall = abi.encodeWithSelector( IInitializableDebtToken.initialize.selector, @@ -217,7 +217,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); - (, , , uint256 decimals, , ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); + (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); bytes memory encodedCall = abi.encodeWithSelector( IInitializableDebtToken.initialize.selector, @@ -446,6 +446,21 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur emit BorrowCapChanged(asset, borrowCap); } + /** + * @dev Updates the supply cap of a reserve + * @param asset The address of the underlying asset of the reserve + * @param supplyCap The new supply of the reserve + **/ + function setSupplyCap(address asset, uint256 supplyCap) external onlyPoolAdmin { + DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + + currentConfig.setSupplyCap(supplyCap); + + pool.setConfiguration(asset, currentConfig.data); + + emit SupplyCapChanged(asset, supplyCap); + } + /** * @dev Sets the interest rate strategy of a reserve * @param asset The address of the underlying asset of the reserve diff --git a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol index 51fabbf9..e849e321 100644 --- a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol @@ -20,6 +20,7 @@ library ReserveConfiguration { uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore uint256 constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 constant SUPPLY_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFF; // 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; @@ -31,6 +32,7 @@ library ReserveConfiguration { uint256 constant STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59; uint256 constant RESERVE_FACTOR_START_BIT_POSITION = 64; uint256 constant BORROW_CAP_START_BIT_POSITION = 80; + uint256 constant SUPPLY_CAP_START_BIT_POSITION = 128; uint256 constant MAX_VALID_LTV = 65535; uint256 constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535; @@ -38,6 +40,7 @@ library ReserveConfiguration { uint256 constant MAX_VALID_DECIMALS = 255; uint256 constant MAX_VALID_RESERVE_FACTOR = 65535; uint256 constant MAX_VALID_BORROW_CAP = 281474976710655; + uint256 constant MAX_VALID_SUPPLY_CAP = 281474976710655; /** * @dev Sets the Loan to Value of the reserve @@ -296,6 +299,35 @@ library ReserveConfiguration { return (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION; } + /** + * @dev Sets the supply cap of the reserve + * @param self The reserve configuration + * @param supplyCap The supply cap + **/ + function setSupplyCap(DataTypes.ReserveConfigurationMap memory self, uint256 supplyCap) + internal + pure + { + require(supplyCap <= MAX_VALID_SUPPLY_CAP, Errors.RC_INVALID_SUPPLY_CAP); + + self.data = + (self.data & SUPPLY_CAP_MASK) | + (supplyCap << SUPPLY_CAP_START_BIT_POSITION); + } + + /** + * @dev Gets the supply cap of the reserve + * @param self The reserve configuration + * @return The supply cap + **/ + function getSupplyCap(DataTypes.ReserveConfigurationMap storage self) + internal + view + returns (uint256) + { + return (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION; + } + /** * @dev Gets the configuration flags of the reserve * @param self The reserve configuration @@ -324,7 +356,7 @@ library ReserveConfiguration { /** * @dev Gets the configuration paramters of the reserve from storage * @param self The reserve configuration - * @return The state params representing ltv, liquidation threshold, liquidation bonus, reserve decimals, reserve factor and borrow cap. + * @return The state params representing ltv, liquidation threshold, liquidation bonus, reserve decimals, reserve factor **/ function getParams(DataTypes.ReserveConfigurationMap storage self) internal @@ -334,7 +366,6 @@ library ReserveConfiguration { uint256, uint256, uint256, - uint256, uint256 ) { @@ -345,15 +376,35 @@ library ReserveConfiguration { (dataLocal & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION, (dataLocal & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION, (dataLocal & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION, - (dataLocal & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION, - (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION + (dataLocal & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION + ); + } + + /** + * @dev Gets the caps paramters of the reserve from storage + * @param self The reserve configuration + * @return The state params representing borrow cap and supply cap. + **/ + function getCaps(DataTypes.ReserveConfigurationMap storage self) + internal + view + returns ( + uint256, + uint256 + ) + { + uint256 dataLocal = self.data; + + return ( + (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION, + (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION ); } /** * @dev Gets the configuration paramters of the reserve from a memory object * @param self The reserve configuration - * @return The state params representing ltv, liquidation threshold, liquidation bonus, reserve decimals, reserve factor, borrow cap + * @return The state params representing ltv, liquidation threshold, liquidation bonus, reserve decimals, reserve factor **/ function getParamsMemory(DataTypes.ReserveConfigurationMap memory self) internal @@ -363,7 +414,6 @@ library ReserveConfiguration { uint256, uint256, uint256, - uint256, uint256 ) { @@ -372,8 +422,26 @@ library ReserveConfiguration { (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION, (self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION, (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION, - (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION, - (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION + (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION + ); + } + + /** + * @dev Gets the caps paramters of the reserve from a memory object + * @param self The reserve configuration + * @return The state params borrow cap and supply cap + **/ + function getCapsMemory(DataTypes.ReserveConfigurationMap memory self) + internal + pure + returns ( + uint256, + uint256 + ) + { + return ( + (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION, + (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION ); } diff --git a/contracts/protocol/libraries/helpers/Errors.sol b/contracts/protocol/libraries/helpers/Errors.sol index 6ee6cced..8ae23f7b 100644 --- a/contracts/protocol/libraries/helpers/Errors.sol +++ b/contracts/protocol/libraries/helpers/Errors.sol @@ -105,6 +105,8 @@ library Errors { string public constant SDT_BURN_EXCEEDS_BALANCE = '80'; string public constant VL_BORROW_CAP_EXCEEDED = '81'; string public constant RC_INVALID_BORROW_CAP = '82'; + string public constant VL_SUPPLY_CAP_EXCEEDED = '83'; + string public constant RC_INVALID_SUPPLY_CAP = '84'; enum CollateralManagerErrors { NO_ERROR, diff --git a/contracts/protocol/libraries/logic/GenericLogic.sol b/contracts/protocol/libraries/logic/GenericLogic.sol index 9f457a17..d4081dda 100644 --- a/contracts/protocol/libraries/logic/GenericLogic.sol +++ b/contracts/protocol/libraries/logic/GenericLogic.sol @@ -68,7 +68,7 @@ library GenericLogic { balanceDecreaseAllowedLocalVars memory vars; - (, vars.liquidationThreshold, , vars.decimals, , ) = reservesData[asset] + (, vars.liquidationThreshold, , vars.decimals, ) = reservesData[asset] .configuration .getParams(); @@ -178,7 +178,7 @@ library GenericLogic { vars.currentReserveAddress = reserves[vars.i]; DataTypes.ReserveData storage currentReserve = reservesData[vars.currentReserveAddress]; - (vars.ltv, vars.liquidationThreshold, , vars.decimals, , ) = currentReserve + (vars.ltv, vars.liquidationThreshold, , vars.decimals, ) = currentReserve .configuration .getParams(); diff --git a/test-suites/test-amm/configurator.spec.ts b/test-suites/test-amm/configurator.spec.ts index 4884d070..4ba20620 100644 --- a/test-suites/test-amm/configurator.spec.ts +++ b/test-suites/test-amm/configurator.spec.ts @@ -178,7 +178,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { 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(true/*strategyWETH.stableBorrowRateEnabled*/); + expect(stableBorrowRateEnabled).to.be.equal(true /*strategyWETH.stableBorrowRateEnabled*/); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(variableBorrowIndex.toString()).to.be.equal(RAY); @@ -195,7 +195,9 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => { const { configurator, users, weth } = testEnv; await expect( - configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, MAX_BORROW_CAP, true), + configurator + .connect(users[2].signer) + .enableBorrowingOnReserve(weth.address, MAX_BORROW_CAP, true), CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); @@ -250,7 +252,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { 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(true/*strategyWETH.stableBorrowRateEnabled*/); + expect(stableBorrowRateEnabled).to.be.equal(true /*strategyWETH.stableBorrowRateEnabled*/); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); }); From 6a0d27c0deab9adcb02d19bd2324255ab0553781 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 30 Apr 2021 16:48:09 +0200 Subject: [PATCH 22/34] fix-refactor: Refactored tests with new getCaps function, fixed contract supplyCap mask --- .../DefaultReserveInterestRateStrategy.sol | 1 - .../configuration/ReserveConfiguration.sol | 2 +- helpers/constants.ts | 1 + helpers/init-helpers.ts | 5 ++ helpers/types.ts | 5 +- markets/aave/reservesConfigs.ts | 27 +++++++++-- markets/amm/reservesConfigs.ts | 22 ++++++++- markets/matic/reservesConfigs.ts | 34 +++++++------ test-suites/test-aave/borrow-cap.spec.ts | 48 +++++++++---------- test-suites/test-aave/configurator.spec.ts | 20 ++++---- 10 files changed, 109 insertions(+), 56 deletions(-) diff --git a/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol b/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol index af4db241..7b321d0c 100644 --- a/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol +++ b/contracts/protocol/lendingpool/DefaultReserveInterestRateStrategy.sol @@ -8,7 +8,6 @@ import {PercentageMath} from '../libraries/math/PercentageMath.sol'; import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; import {ILendingRateOracle} from '../../interfaces/ILendingRateOracle.sol'; import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol'; -import 'hardhat/console.sol'; /** * @title DefaultReserveInterestRateStrategy contract diff --git a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol index e849e321..77375778 100644 --- a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol @@ -20,7 +20,7 @@ library ReserveConfiguration { uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore uint256 constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore - uint256 constant SUPPLY_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 constant SUPPLY_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // 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; diff --git a/helpers/constants.ts b/helpers/constants.ts index 47371513..a0274bcc 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -16,6 +16,7 @@ export const oneRay = new BigNumber(Math.pow(10, 27)); export const MAX_UINT_AMOUNT = '115792089237316195423570985008687907853269984665640564039457584007913129639935'; export const MAX_BORROW_CAP = '281474976710655'; +export const MAX_SUPPLY_CAP = '281474976710655'; 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 65c3a14e..8f9e145c 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -276,6 +276,7 @@ export const configureReservesByHelper = async ( const liquidationBonuses: string[] = []; const reserveFactors: string[] = []; const borrowCaps: string[] = []; + const supplyCaps: string[] = []; const stableRatesEnabled: boolean[] = []; const inputParams: { @@ -285,6 +286,7 @@ export const configureReservesByHelper = async ( liquidationBonus: BigNumberish; reserveFactor: BigNumberish; borrowCap: BigNumberish; + supplyCap: BigNumberish; stableBorrowingEnabled: boolean; }[] = []; @@ -296,6 +298,7 @@ export const configureReservesByHelper = async ( liquidationThreshold, reserveFactor, borrowCap, + supplyCap, stableBorrowRateEnabled, }, ] of Object.entries(reservesParams) as [string, IReserveParams][]) { @@ -324,6 +327,7 @@ export const configureReservesByHelper = async ( liquidationBonus, reserveFactor, borrowCap, + supplyCap, stableBorrowingEnabled: stableBorrowRateEnabled, }); @@ -334,6 +338,7 @@ export const configureReservesByHelper = async ( liquidationBonuses.push(liquidationBonus); reserveFactors.push(reserveFactor); borrowCaps.push(borrowCap); + supplyCaps.push(supplyCap); stableRatesEnabled.push(stableBorrowRateEnabled); } if (tokens.length) { diff --git a/helpers/types.ts b/helpers/types.ts index dd8cec9e..b50894cc 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -353,12 +353,13 @@ export enum TokenContractId { BptBALWETH = 'BptBALWETH', WMATIC = 'WMATIC', STAKE = 'STAKE', - xSUSHI = 'xSUSHI' + xSUSHI = 'xSUSHI', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { aTokenImpl: eContractid; reserveFactor: string; + supplyCap: string; strategy: IInterestRateStrategyParams; } @@ -382,13 +383,13 @@ export interface IReserveBorrowParams { borrowingEnabled: boolean; stableBorrowRateEnabled: boolean; reserveDecimals: string; + borrowCap: string; } export interface IReserveCollateralParams { baseLTVAsCollateral: string; liquidationThreshold: string; liquidationBonus: string; - borrowCap: string; } export interface IMarketRates { borrowRate: string; diff --git a/markets/aave/reservesConfigs.ts b/markets/aave/reservesConfigs.ts index 6f33a99d..c0be1118 100644 --- a/markets/aave/reservesConfigs.ts +++ b/markets/aave/reservesConfigs.ts @@ -1,7 +1,7 @@ -import { MAX_BORROW_CAP } from '../../helpers/constants'; +import { MAX_BORROW_CAP, MAX_SUPPLY_CAP } from '../../helpers/constants'; import { eContractid, IReserveParams } from '../../helpers/types'; -import { +import { rateStrategyStableOne, rateStrategyStableTwo, rateStrategyStableThree, @@ -24,6 +24,7 @@ export const strategyBUSD: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyDAI: IReserveParams = { @@ -37,6 +38,7 @@ export const strategyDAI: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategySUSD: IReserveParams = { @@ -50,6 +52,7 @@ export const strategySUSD: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyTUSD: IReserveParams = { @@ -63,6 +66,7 @@ export const strategyTUSD: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyUSDC: IReserveParams = { @@ -76,6 +80,7 @@ export const strategyUSDC: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyUSDT: IReserveParams = { @@ -89,6 +94,7 @@ export const strategyUSDT: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyAAVE: IReserveParams = { @@ -102,6 +108,7 @@ export const strategyAAVE: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '0', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyBAT: IReserveParams = { @@ -115,6 +122,7 @@ export const strategyBAT: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyENJ: IReserveParams = { @@ -128,6 +136,7 @@ export const strategyENJ: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyWETH: IReserveParams = { @@ -141,6 +150,7 @@ export const strategyWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyKNC: IReserveParams = { @@ -154,6 +164,7 @@ export const strategyKNC: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyLINK: IReserveParams = { @@ -167,6 +178,7 @@ export const strategyLINK: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyMANA: IReserveParams = { @@ -180,6 +192,7 @@ export const strategyMANA: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '3500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyMKR: IReserveParams = { @@ -193,6 +206,7 @@ export const strategyMKR: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyREN: IReserveParams = { @@ -206,6 +220,7 @@ export const strategyREN: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategySNX: IReserveParams = { @@ -219,6 +234,7 @@ export const strategySNX: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '3500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; // Invalid borrow rates in params currently, replaced with snx params @@ -233,6 +249,7 @@ export const strategyUNI: IReserveParams = { aTokenImpl: eContractid.DelegationAwareAToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyWBTC: IReserveParams = { @@ -246,6 +263,7 @@ export const strategyWBTC: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyYFI: IReserveParams = { @@ -259,6 +277,7 @@ export const strategyYFI: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyZRX: IReserveParams = { @@ -272,6 +291,7 @@ export const strategyZRX: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyXSUSHI: IReserveParams = { @@ -285,4 +305,5 @@ export const strategyXSUSHI: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '3500', borrowCap: MAX_BORROW_CAP, -}; \ No newline at end of file + supplyCap: MAX_SUPPLY_CAP, +}; diff --git a/markets/amm/reservesConfigs.ts b/markets/amm/reservesConfigs.ts index c443953b..8f0f06fa 100644 --- a/markets/amm/reservesConfigs.ts +++ b/markets/amm/reservesConfigs.ts @@ -1,4 +1,4 @@ -import { MAX_BORROW_CAP } from '../../helpers/constants'; +import { MAX_BORROW_CAP, MAX_SUPPLY_CAP } from '../../helpers/constants'; import { eContractid, IReserveParams} from '../../helpers/types'; import { rateStrategyAmmBase, @@ -18,6 +18,7 @@ export const strategyWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyWBTC: IReserveParams = { @@ -31,6 +32,7 @@ export const strategyWBTC: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyDAI: IReserveParams = { @@ -44,6 +46,7 @@ export const strategyDAI: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyUSDC: IReserveParams = { @@ -57,6 +60,7 @@ export const strategyUSDC: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyUSDT: IReserveParams = { @@ -70,6 +74,7 @@ export const strategyUSDT: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyDAIWETH: IReserveParams = { @@ -83,6 +88,7 @@ export const strategyDAIWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyWBTCWETH: IReserveParams = { @@ -96,6 +102,7 @@ export const strategyWBTCWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyAAVEWETH: IReserveParams = { @@ -109,6 +116,7 @@ export const strategyAAVEWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyBATWETH: IReserveParams = { @@ -122,6 +130,7 @@ export const strategyBATWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyDAIUSDC: IReserveParams = { @@ -135,6 +144,7 @@ export const strategyDAIUSDC: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyCRVWETH: IReserveParams = { @@ -148,6 +158,7 @@ export const strategyCRVWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyLINKWETH: IReserveParams = { @@ -161,6 +172,7 @@ export const strategyLINKWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyMKRWETH: IReserveParams = { @@ -174,6 +186,7 @@ export const strategyMKRWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyRENWETH: IReserveParams = { @@ -187,6 +200,7 @@ export const strategyRENWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategySNXWETH: IReserveParams = { @@ -200,6 +214,7 @@ export const strategySNXWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyUNIWETH: IReserveParams = { @@ -213,6 +228,7 @@ export const strategyUNIWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyUSDCWETH: IReserveParams = { @@ -226,6 +242,7 @@ export const strategyUSDCWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyWBTCUSDC: IReserveParams = { @@ -239,6 +256,7 @@ export const strategyWBTCUSDC: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyYFIWETH: IReserveParams = { @@ -252,6 +270,7 @@ export const strategyYFIWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyBALWETH: IReserveParams = { @@ -265,4 +284,5 @@ export const strategyBALWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1500', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, } \ No newline at end of file diff --git a/markets/matic/reservesConfigs.ts b/markets/matic/reservesConfigs.ts index 66acf51e..c38e5855 100644 --- a/markets/matic/reservesConfigs.ts +++ b/markets/matic/reservesConfigs.ts @@ -1,8 +1,8 @@ // import BigNumber from 'bignumber.js'; // import { oneRay } from '../../helpers/constants'; -import { MAX_BORROW_CAP } from '../../helpers/constants'; +import { MAX_BORROW_CAP, MAX_SUPPLY_CAP } from '../../helpers/constants'; import { eContractid, IReserveParams } from '../../helpers/types'; -import { +import { rateStrategyStableOne, rateStrategyStableTwo, rateStrategyStableThree, @@ -24,6 +24,7 @@ export const strategyDAI: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyUSDC: IReserveParams = { @@ -37,19 +38,21 @@ export const strategyUSDC: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyUSDT: IReserveParams = { - strategy: rateStrategyStableThree, - baseLTVAsCollateral: '8000', - liquidationThreshold: '8500', - liquidationBonus: '10500', - borrowingEnabled: true, - stableBorrowRateEnabled: true, - reserveDecimals: '6', - aTokenImpl: eContractid.AToken, - reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, + strategy: rateStrategyStableThree, + baseLTVAsCollateral: '8000', + liquidationThreshold: '8500', + liquidationBonus: '10500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '6', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000', + borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyWETH: IReserveParams = { @@ -63,6 +66,7 @@ export const strategyWETH: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '1000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyWBTC: IReserveParams = { @@ -76,10 +80,11 @@ export const strategyWBTC: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, }; export const strategyMATIC: IReserveParams = { - strategy: rateStrategyVolatileOne, //Temp? + strategy: rateStrategyVolatileOne, //Temp? baseLTVAsCollateral: '5000', liquidationThreshold: '6500', liquidationBonus: '11000', @@ -89,4 +94,5 @@ export const strategyMATIC: IReserveParams = { aTokenImpl: eContractid.AToken, reserveFactor: '2000', borrowCap: MAX_BORROW_CAP, -}; \ No newline at end of file + supplyCap: MAX_SUPPLY_CAP, +}; diff --git a/test-suites/test-aave/borrow-cap.spec.ts b/test-suites/test-aave/borrow-cap.spec.ts index 6b127855..efae3b6f 100644 --- a/test-suites/test-aave/borrow-cap.spec.ts +++ b/test-suites/test-aave/borrow-cap.spec.ts @@ -42,8 +42,8 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { 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); - let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); - let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; expect(usdcBorrowCap).to.be.equal(MAX_BORROW_CAP); expect(daiBorrowCap).to.be.equal(MAX_BORROW_CAP); @@ -53,8 +53,8 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { await configurator.setBorrowCap(usdc.address, 0); await configurator.setBorrowCap(dai.address, 0); - usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); - daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; expect(usdcBorrowCap).to.be.equal(0); expect(daiBorrowCap).to.be.equal(0); @@ -97,8 +97,8 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { it('Should fail to set the borrow cap for usdc and DAI to max cap + 1 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; const newCap = Number(MAX_BORROW_CAP) + 1; - let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); - let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; expect(usdcBorrowCap).to.be.equal(0); expect(daiBorrowCap).to.be.equal(0); @@ -110,14 +110,14 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { RC_INVALID_BORROW_CAP ); - usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); - daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; }); it('Sets the borrow cap for usdc and DAI to 110 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; const newCap = '110'; - let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); - let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; expect(usdcBorrowCap).to.be.equal(0); expect(daiBorrowCap).to.be.equal(0); @@ -125,8 +125,8 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { await configurator.setBorrowCap(usdc.address, newCap); await configurator.setBorrowCap(dai.address, newCap); - usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); - daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; expect(usdcBorrowCap).to.be.equal(newCap); expect(daiBorrowCap).to.be.equal(newCap); @@ -199,14 +199,14 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { it('Raises the borrow cap for usdc and DAI to 1000 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; const newCap = '1000'; - let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); - let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; await configurator.setBorrowCap(usdc.address, newCap); await configurator.setBorrowCap(dai.address, newCap); - usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); - daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; expect(usdcBorrowCap).to.be.equal(newCap); expect(daiBorrowCap).to.be.equal(newCap); @@ -235,14 +235,14 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { it('Lowers the borrow cap for usdc and DAI to 200 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; const newCap = '200'; - let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); - let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; await configurator.setBorrowCap(usdc.address, newCap); await configurator.setBorrowCap(dai.address, newCap); - usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); - daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; expect(usdcBorrowCap).to.be.equal(newCap); expect(daiBorrowCap).to.be.equal(newCap); @@ -275,14 +275,14 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { it('Raises the borrow cap for usdc and DAI to max cap Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; const newCap = MAX_BORROW_CAP; - let usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); - let daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; await configurator.setBorrowCap(usdc.address, newCap); await configurator.setBorrowCap(dai.address, newCap); - usdcBorrowCap = await helpersContract.getReserveBorrowCap(usdc.address); - daiBorrowCap = await helpersContract.getReserveBorrowCap(dai.address); + usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; expect(usdcBorrowCap).to.be.equal(newCap); expect(daiBorrowCap).to.be.equal(newCap); diff --git a/test-suites/test-aave/configurator.spec.ts b/test-suites/test-aave/configurator.spec.ts index 9a3bfc2f..ea4f53bc 100644 --- a/test-suites/test-aave/configurator.spec.ts +++ b/test-suites/test-aave/configurator.spec.ts @@ -75,7 +75,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -104,7 +104,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -148,7 +148,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); expect(borrowingEnabled).to.be.equal(false); expect(isActive).to.be.equal(true); @@ -178,7 +178,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -227,7 +227,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -256,7 +256,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -294,7 +294,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -322,7 +322,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -382,7 +382,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); @@ -418,7 +418,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); - const borrowCap = await helpersContract.getReserveBorrowCap(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); From be859bd2704ab247ab693cc91285cbf5d18ff32d Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 30 Apr 2021 16:55:31 +0200 Subject: [PATCH 23/34] test: added supply cap tests in configurator test --- helpers/types.ts | 2 + test-suites/test-aave/configurator.spec.ts | 54 ++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/helpers/types.ts b/helpers/types.ts index b50894cc..a54ba0ba 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -180,6 +180,8 @@ export enum ProtocolErrors { LPAPR_INVALID_ADDRESSES_PROVIDER_ID = '72', VL_BORROW_CAP_EXCEEDED = '81', RC_INVALID_BORROW_CAP = '82', + VL_SUPPLY_CAP_EXCEEDED = '83', + RC_INVALID_SUPPLY_CAP = '84', // old diff --git a/test-suites/test-aave/configurator.spec.ts b/test-suites/test-aave/configurator.spec.ts index ea4f53bc..d4e3d0f1 100644 --- a/test-suites/test-aave/configurator.spec.ts +++ b/test-suites/test-aave/configurator.spec.ts @@ -17,6 +17,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { RC_INVALID_DECIMALS, RC_INVALID_RESERVE_FACTOR, RC_INVALID_BORROW_CAP, + RC_INVALID_SUPPLY_CAP, } = ProtocolErrors; it('Reverts trying to set an invalid reserve factor', async () => { @@ -87,6 +88,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); it('Unfreezes the ETH reserve', async () => { @@ -116,6 +118,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); it('Check the onlyAaveAdmin on freezeReserve ', async () => { @@ -160,6 +163,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); it('Activates the ETH reserve for borrowing', async () => { @@ -190,6 +194,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); expect(variableBorrowIndex.toString()).to.be.equal(RAY); }); @@ -239,6 +244,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(stableBorrowRateEnabled).to.be.equal(true); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); it('Activates the ETH reserve as collateral', async () => { @@ -268,6 +274,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); it('Check the onlyAaveAdmin on configureReserveAsCollateral ', async () => { @@ -306,6 +313,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(stableBorrowRateEnabled).to.be.equal(false); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); it('Enables stable borrow rate on the ETH reserve', async () => { @@ -334,6 +342,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(stableBorrowRateEnabled).to.be.equal(true); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); it('Check the onlyAaveAdmin on disableReserveStableRate', async () => { @@ -367,6 +376,13 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); + it('Check the onlyAaveAdmin on setSupplyCap', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.connect(users[2].signer).setSupplyCap(weth.address, '3000000000'), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + }); it('Changes the reserve factor of WETH', async () => { const { configurator, helpersContract, weth } = testEnv; @@ -393,6 +409,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); expect(reserveFactor).to.be.equal(1000); }); @@ -403,6 +420,13 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(RC_INVALID_BORROW_CAP); }); + it('Fails to change to too high supplyCap', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.setSupplyCap(weth.address, BigNumber.from(MAX_BORROW_CAP).add(1)), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(RC_INVALID_SUPPLY_CAP); + }); it('Changes the borrow Cap of WETH', async () => { const { configurator, helpersContract, weth } = testEnv; @@ -430,6 +454,36 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(1000); expect(borrowCap).to.be.equal('3000000'); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + }); + + it('Changes the borrow Cap of WETH', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.setSupplyCap(weth.address, '3000000'); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + 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'); }); it('Reverts when trying to disable the DAI reserve with liquidity on it', async () => { From 1de5a303f43a9641a7079116b0d8fad3e996106a Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 30 Apr 2021 17:35:16 +0200 Subject: [PATCH 24/34] feat: implemented supply cap --- contracts/protocol/libraries/logic/ValidationLogic.sol | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index bb697fe6..daa048fd 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -46,6 +46,13 @@ library ValidationLogic { require(amount != 0, Errors.VL_INVALID_AMOUNT); require(isActive, Errors.VL_NO_ACTIVE_RESERVE); require(!isFrozen, Errors.VL_RESERVE_FROZEN); + require( + IERC20(reserve.aTokenAddress) + .totalSupply() + .add(amount) + .div(10 ** reserve.configuration.getDecimals()) < reserve.configuration.getSupplyCap(), + Errors.VL_SUPPLY_CAP_EXCEEDED + ); } /** From 1bec5270917d222258b0a5271beb18454c41b3c2 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 30 Apr 2021 17:35:46 +0200 Subject: [PATCH 25/34] test: tested supply cap --- package.json | 1 + test-suites/test-aave/borrow-cap.spec.ts | 2 +- test-suites/test-aave/supply-cap.spec.ts | 276 +++++++++++++++++++++++ 3 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 test-suites/test-aave/supply-cap.spec.ts diff --git a/package.json b/package.json index eb49517b..e984ac3c 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "test-liquidate-underlying": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/liquidation-underlying.spec.ts", "test-configurator": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/configurator.spec.ts", "test-borrow-cap": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/borrow-cap.spec.ts", + "test-supply-cap": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/supply-cap.spec.ts", "test-transfers": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-transfer.spec.ts", "test-flash": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/flashloan.spec.ts", "test-liquidate": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/liquidation-atoken.spec.ts", diff --git a/test-suites/test-aave/borrow-cap.spec.ts b/test-suites/test-aave/borrow-cap.spec.ts index efae3b6f..6693b8c4 100644 --- a/test-suites/test-aave/borrow-cap.spec.ts +++ b/test-suites/test-aave/borrow-cap.spec.ts @@ -151,7 +151,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { deployer.address ); }); - it('should fail to borrow 100 variable dai and 100 stable usdc (interests accrued)', async () => { + it('should fail to borrow 100 variable dai and 100 stable usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const borrowedAmount = 100; const borrowedMilimount = (borrowedAmount * 1000).toString(); diff --git a/test-suites/test-aave/supply-cap.spec.ts b/test-suites/test-aave/supply-cap.spec.ts new file mode 100644 index 00000000..8c35d197 --- /dev/null +++ b/test-suites/test-aave/supply-cap.spec.ts @@ -0,0 +1,276 @@ +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { + APPROVAL_AMOUNT_LENDING_POOL, + MAX_UINT_AMOUNT, + RAY, + MAX_SUPPLY_CAP, +} from '../../helpers/constants'; +import { ProtocolErrors } from '../../helpers/types'; +import { MintableERC20, WETH9, WETH9Mocked } from '../../types'; +import { parseEther } from '@ethersproject/units'; +import { BigNumber } from '@ethersproject/bignumber'; + +const { expect } = require('chai'); + +makeSuite('supply Cap', (testEnv: TestEnv) => { + const { VL_SUPPLY_CAP_EXCEEDED, RC_INVALID_SUPPLY_CAP } = ProtocolErrors; + + const miliUnitToPrecision = async (token: WETH9Mocked | MintableERC20, nb: string) => + BigNumber.from(nb).mul(BigNumber.from('10').pow((await token.decimals()) - 3)); + + it('Sets the supply cap for Weth and DAI to 0 Units, deposits weth', async () => { + const { + configurator, + weth, + pool, + dai, + usdc, + deployer, + helpersContract, + users: [user1], + } = testEnv; + const mintedAmount = parseEther('1000000000'); + await dai.mint(mintedAmount); + await weth.mint(mintedAmount); + await usdc.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); + let usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + let daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcsupplyCap).to.be.equal(MAX_SUPPLY_CAP); + expect(daisupplyCap).to.be.equal(MAX_SUPPLY_CAP); + + const depositedMiliAmount = (1e9).toString(); + + await configurator.setSupplyCap(usdc.address, 0); + await configurator.setSupplyCap(dai.address, 0); + + usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcsupplyCap).to.be.equal(0); + expect(daisupplyCap).to.be.equal(0); + }); + it('should fail to supply any dai or usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 10; + const suppliedMilimount = (suppliedAmount * 1000).toString(); + + await expect( + pool.deposit( + usdc.address, + await miliUnitToPrecision(usdc, suppliedMilimount), + deployer.address, + 0 + ) + ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); + + await expect( + pool.deposit( + dai.address, + await miliUnitToPrecision(dai, suppliedMilimount), + deployer.address, + 0 + ) + ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); + }); + it('Should fail to set the supply cap for usdc and DAI to max cap + 1 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = Number(MAX_SUPPLY_CAP) + 1; + let usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + let daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcsupplyCap).to.be.equal(0); + expect(daisupplyCap).to.be.equal(0); + + await expect(configurator.setSupplyCap(usdc.address, newCap)).to.be.revertedWith( + RC_INVALID_SUPPLY_CAP + ); + await expect(configurator.setSupplyCap(dai.address, newCap)).to.be.revertedWith( + RC_INVALID_SUPPLY_CAP + ); + }); + it('Sets the supply cap for usdc and DAI to 110 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = '110'; + let usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + let daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcsupplyCap).to.be.equal(0); + expect(daisupplyCap).to.be.equal(0); + + await configurator.setSupplyCap(usdc.address, newCap); + await configurator.setSupplyCap(dai.address, newCap); + + usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcsupplyCap).to.be.equal(newCap); + expect(daisupplyCap).to.be.equal(newCap); + }); + it('Should succeed to supply 10 dai and 10 usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 10; + const suppliedMilimount = (suppliedAmount * 1000).toString(); + await pool.deposit( + usdc.address, + await miliUnitToPrecision(usdc, suppliedMilimount), + deployer.address, + 0 + ); + + await pool.deposit( + dai.address, + await miliUnitToPrecision(dai, suppliedMilimount), + deployer.address, + 0 + ); + }); + it('should fail to supply 100 dai and 100 usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 100; + const suppliedMilimount = (suppliedAmount * 1000).toString(); + + await expect( + pool.deposit( + usdc.address, + await miliUnitToPrecision(usdc, suppliedMilimount), + deployer.address, + 0 + ) + ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); + + await expect( + pool.deposit( + dai.address, + await miliUnitToPrecision(dai, suppliedMilimount), + deployer.address, + 0 + ) + ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); + }); + it('Should succeed to supply 99 dai and 99 usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 99; + const suppliedMilimount = (suppliedAmount * 1000).toString(); + await pool.deposit( + usdc.address, + await miliUnitToPrecision(usdc, suppliedMilimount), + deployer.address, + 0 + ); + + await pool.deposit( + dai.address, + await miliUnitToPrecision(dai, suppliedMilimount), + deployer.address, + 0 + ); + }); + it('Raises the supply cap for usdc and DAI to 1000 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = '1000'; + let usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + let daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + await configurator.setSupplyCap(usdc.address, newCap); + await configurator.setSupplyCap(dai.address, newCap); + + usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcsupplyCap).to.be.equal(newCap); + expect(daisupplyCap).to.be.equal(newCap); + }); + it('should succeed to supply 100 dai and 100 usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 100; + const suppliedMilimount = (suppliedAmount * 1000).toString(); + await pool.deposit( + usdc.address, + await miliUnitToPrecision(usdc, suppliedMilimount), + deployer.address, + 0 + ); + + await pool.deposit( + dai.address, + await miliUnitToPrecision(dai, suppliedMilimount), + deployer.address, + 0 + ); + }); + it('Lowers the supply cap for usdc and DAI to 200 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = '200'; + let usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + let daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + await configurator.setSupplyCap(usdc.address, newCap); + await configurator.setSupplyCap(dai.address, newCap); + + usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcsupplyCap).to.be.equal(newCap); + expect(daisupplyCap).to.be.equal(newCap); + }); + it('should fail to supply 100 dai and 100 usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 100; + const suppliedMilimount = (suppliedAmount * 1000).toString(); + + await expect( + pool.deposit( + usdc.address, + await miliUnitToPrecision(usdc, suppliedMilimount), + deployer.address, + 0 + ) + ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); + + await expect( + pool.deposit( + dai.address, + await miliUnitToPrecision(dai, suppliedMilimount), + deployer.address, + 0 + ) + ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); + }); + it('Raises the supply cap for usdc and DAI to max cap Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = MAX_SUPPLY_CAP; + let usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + let daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + await configurator.setSupplyCap(usdc.address, newCap); + await configurator.setSupplyCap(dai.address, newCap); + + usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcsupplyCap).to.be.equal(newCap); + expect(daisupplyCap).to.be.equal(newCap); + }); + it('should succeed to supply 100 dai and 100 usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 100; + const suppliedMilimount = (suppliedAmount * 1000).toString(); + await pool.deposit( + usdc.address, + await miliUnitToPrecision(usdc, suppliedMilimount), + deployer.address, + 0 + ); + + await pool.deposit( + dai.address, + await miliUnitToPrecision(dai, suppliedMilimount), + deployer.address, + 0 + ); + }); +}); From 6a952901d9afadefcf1f6775f0b6ece14b835834 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Fri, 30 Apr 2021 17:43:00 +0200 Subject: [PATCH 26/34] doc: documented new reserveConfigurationMap data structure --- contracts/protocol/libraries/types/DataTypes.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/protocol/libraries/types/DataTypes.sol b/contracts/protocol/libraries/types/DataTypes.sol index 26a041ab..419efe59 100644 --- a/contracts/protocol/libraries/types/DataTypes.sol +++ b/contracts/protocol/libraries/types/DataTypes.sol @@ -39,6 +39,7 @@ library DataTypes { //bit 60-63: reserved //bit 64-79: reserve factor //bit 80-127 borrow cap + //bit 128-175 borrow cap uint256 data; } From 72eb085c12202808d24e612ff7ff8f7ce3321389 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Mon, 17 May 2021 13:08:07 +0200 Subject: [PATCH 27/34] fix: updated test with correct deposited amounts --- test-suites/test-aave/borrow-cap.spec.ts | 29 +++++++++++++++--------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/test-suites/test-aave/borrow-cap.spec.ts b/test-suites/test-aave/borrow-cap.spec.ts index 6693b8c4..3b2a894c 100644 --- a/test-suites/test-aave/borrow-cap.spec.ts +++ b/test-suites/test-aave/borrow-cap.spec.ts @@ -4,6 +4,7 @@ import { MAX_UINT_AMOUNT, RAY, MAX_BORROW_CAP, + MAX_SUPPLY_CAP, } from '../../helpers/constants'; import { ProtocolErrors } from '../../helpers/types'; import { MintableERC20, WETH9, WETH9Mocked } from '../../types'; @@ -29,13 +30,16 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { helpersContract, users: [user1], } = testEnv; - const mintedAmount = parseEther('1000000000'); - await dai.mint(mintedAmount); - await weth.mint(mintedAmount); - await usdc.mint(mintedAmount); - await dai.connect(user1.signer).mint(mintedAmount); - await weth.connect(user1.signer).mint(mintedAmount); - await usdc.connect(user1.signer).mint(mintedAmount); + const mintedMiliAmount = '1000000000000'; + const daiMinted = await miliUnitToPrecision(dai, mintedMiliAmount); + const wethMinted = await miliUnitToPrecision(weth, mintedMiliAmount); + const usdcMinted = await miliUnitToPrecision(usdc, mintedMiliAmount); + await dai.mint(daiMinted); + await weth.mint(wethMinted); + await usdc.mint(usdcMinted); + await dai.connect(user1.signer).mint(daiMinted); + await weth.connect(user1.signer).mint(wethMinted); + await usdc.connect(user1.signer).mint(usdcMinted); await dai.approve(pool.address, MAX_UINT_AMOUNT); await weth.approve(pool.address, MAX_UINT_AMOUNT); await usdc.approve(pool.address, MAX_UINT_AMOUNT); @@ -44,9 +48,12 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { await usdc.connect(user1.signer).approve(pool.address, MAX_UINT_AMOUNT); let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; - expect(usdcBorrowCap).to.be.equal(MAX_BORROW_CAP); expect(daiBorrowCap).to.be.equal(MAX_BORROW_CAP); + let wethBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; + let wethSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + expect(wethBorrowCap).to.be.equal(MAX_BORROW_CAP); + expect(wethSupplyCap).to.be.equal(MAX_SUPPLY_CAP); const depositedMiliAmount = (1e9).toString(); @@ -65,9 +72,9 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { deployer.address, 0 ); - await pool.connect(user1.signer).deposit(weth.address, mintedAmount, user1.address, 0); - await pool.connect(user1.signer).deposit(dai.address, mintedAmount, user1.address, 0); - await pool.connect(user1.signer).deposit(usdc.address, mintedAmount, user1.address, 0); + await pool.connect(user1.signer).deposit(weth.address, wethMinted, user1.address, 0); + await pool.connect(user1.signer).deposit(dai.address, daiMinted, user1.address, 0); + await pool.connect(user1.signer).deposit(usdc.address, usdcMinted, user1.address, 0); }); it('should fail to borrow any dai or usdc, stable or variable', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; From 56bf996885cf346189dc8ea7d67b0ec3cf03ac67 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 25 May 2021 09:48:08 +0200 Subject: [PATCH 28/34] fix: configurator: added event borrowCapChanged in enableBorrowingOnReserve function --- .../lendingpool/LendingPoolConfigurator.sol | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol index 85cd32cf..4b8662c7 100644 --- a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol @@ -151,7 +151,8 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); - bytes memory encodedCall = abi.encodeWithSelector( + bytes memory encodedCall = + abi.encodeWithSelector( IInitializableAToken.initialize.selector, cachedPool, input.treasury, @@ -163,11 +164,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur input.params ); - _upgradeTokenImplementation( - reserveData.aTokenAddress, - input.implementation, - encodedCall - ); + _upgradeTokenImplementation(reserveData.aTokenAddress, input.implementation, encodedCall); emit ATokenUpgraded(input.asset, reserveData.aTokenAddress, input.implementation); } @@ -179,10 +176,11 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur ILendingPool cachedPool = pool; DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); - + (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); - bytes memory encodedCall = abi.encodeWithSelector( + bytes memory encodedCall = + abi.encodeWithSelector( IInitializableDebtToken.initialize.selector, cachedPool, input.asset, @@ -209,17 +207,15 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur /** * @dev Updates the variable debt token implementation for the asset **/ - function updateVariableDebtToken(UpdateDebtTokenInput calldata input) - external - onlyPoolAdmin - { + function updateVariableDebtToken(UpdateDebtTokenInput calldata input) external onlyPoolAdmin { ILendingPool cachedPool = pool; DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); - bytes memory encodedCall = abi.encodeWithSelector( + bytes memory encodedCall = + abi.encodeWithSelector( IInitializableDebtToken.initialize.selector, cachedPool, input.asset, @@ -248,10 +244,11 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur * @param asset The address of the underlying asset of the reserve * @param stableBorrowRateEnabled True if stable borrow rate needs to be enabled by default on this reserve **/ - function enableBorrowingOnReserve(address asset, uint256 borrowCap, bool stableBorrowRateEnabled) - external - onlyPoolAdmin - { + function enableBorrowingOnReserve( + address asset, + uint256 borrowCap, + bool stableBorrowRateEnabled + ) external onlyPoolAdmin { DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); currentConfig.setBorrowingEnabled(true); @@ -260,6 +257,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur pool.setConfiguration(asset, currentConfig.data); + emit BorrowCapChanged(asset, borrowCap); emit BorrowingEnabledOnReserve(asset, stableBorrowRateEnabled); } From 7a40b944df4a249f3870a05635e6e1f940d9e8b6 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 25 May 2021 11:22:13 +0200 Subject: [PATCH 29/34] fix: cached reserve parameters in validateDeposit and validateBorrow --- .../libraries/logic/ValidationLogic.sol | 57 +++++++++---------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index 6473ebfe..08cffe5c 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -41,21 +41,20 @@ library ValidationLogic { * @param amount The amount to be deposited */ function validateDeposit(DataTypes.ReserveData storage reserve, uint256 amount) internal view { - (bool isActive, bool isFrozen, , ) = reserve.configuration.getFlags(); + DataTypes.ReserveConfigurationMap memory reserveConfiguration = reserve.configuration; + (bool isActive, bool isFrozen, , ) = reserveConfiguration.getFlagsMemory(); + (, , , uint256 reserveDecimals, ) = reserveConfiguration.getParamsMemory(); require(amount != 0, Errors.VL_INVALID_AMOUNT); require(isActive, Errors.VL_NO_ACTIVE_RESERVE); require(!isFrozen, Errors.VL_RESERVE_FROZEN); require( - IERC20(reserve.aTokenAddress) - .totalSupply() - .add(amount) - .div(10 ** reserve.configuration.getDecimals()) < reserve.configuration.getSupplyCap(), + IERC20(reserve.aTokenAddress).totalSupply().add(amount).div(10**reserveDecimals) < + reserveConfiguration.getSupplyCapMemory(), Errors.VL_SUPPLY_CAP_EXCEEDED ); } - /** * @dev Validates a withdraw action * @param reserve The reserve object @@ -66,7 +65,7 @@ library ValidationLogic { DataTypes.ReserveData storage reserve, uint256 amount, uint256 userBalance - ) internal view { + ) external view { require(amount != 0, Errors.VL_INVALID_AMOUNT); require(amount <= userBalance, Errors.VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE); @@ -84,6 +83,7 @@ library ValidationLogic { uint256 healthFactor; uint256 totalSupplyStableDebt; uint256 totalSupplyVariableDebt; + uint256 reserveDecimals; bool isActive; bool isFrozen; bool borrowingEnabled; @@ -121,9 +121,15 @@ library ValidationLogic { ) internal view { ValidateBorrowLocalVars memory vars; - (vars.isActive, vars.isFrozen, vars.borrowingEnabled, vars.stableRateBorrowingEnabled) = reserve - .configuration - .getFlags(); + DataTypes.ReserveConfigurationMap memory reserveConfiguration = reserve.configuration; + (, , , vars.reserveDecimals, ) = reserveConfiguration.getParamsMemory(); + + ( + vars.isActive, + vars.isFrozen, + vars.borrowingEnabled, + vars.stableRateBorrowingEnabled + ) = reserveConfiguration.getFlagsMemory(); require(vars.isActive, Errors.VL_NO_ACTIVE_RESERVE); require(!vars.isFrozen, Errors.VL_RESERVE_FROZEN); @@ -137,22 +143,17 @@ library ValidationLogic { uint256(DataTypes.InterestRateMode.STABLE) == interestRateMode, Errors.VL_INVALID_INTEREST_RATE_MODE_SELECTED ); - - (vars.totalSupplyStableDebt, ) = IStableDebtToken(reserve.stableDebtTokenAddress) - .getTotalSupplyAndAvgRate(); - vars.totalSupplyVariableDebt = IVariableDebtToken(reserve.variableDebtTokenAddress) - .scaledTotalSupply() - .rayMul(reserve.variableBorrowIndex); - - + vars.totalSupplyStableDebt = IERC20(reserve.stableDebtTokenAddress).totalSupply(); + + vars.totalSupplyVariableDebt = IERC20(reserve.variableDebtTokenAddress).totalSupply(); + require( - vars.totalSupplyStableDebt - .add(vars.totalSupplyVariableDebt) - .add(amount) - .div(10 ** reserve.configuration.getDecimals()) - < reserve.configuration.getBorrowCap(), - Errors.VL_BORROW_CAP_EXCEEDED); + vars.totalSupplyStableDebt.add(vars.totalSupplyVariableDebt).add(amount).div( + 10**vars.reserveDecimals + ) < reserveConfiguration.getBorrowCapMemory(), + Errors.VL_BORROW_CAP_EXCEEDED + ); ( vars.userCollateralBalanceETH, @@ -231,7 +232,7 @@ library ValidationLogic { address onBehalfOf, uint256 stableDebt, uint256 variableDebt - ) internal view { + ) external view { bool isActive = reserve.configuration.getActive(); require(isActive, Errors.VL_NO_ACTIVE_RESERVE); @@ -340,9 +341,7 @@ library ValidationLogic { * @dev Validates the action of setting an asset as collateral * @param reserve The state of the reserve that the user is enabling or disabling as collateral */ - function validateSetUseReserveAsCollateral( - DataTypes.ReserveData storage reserve - ) external view { + function validateSetUseReserveAsCollateral(DataTypes.ReserveData storage reserve) external view { uint256 underlyingBalance = IERC20(reserve.aTokenAddress).balanceOf(msg.sender); require(underlyingBalance > 0, Errors.VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0); @@ -353,7 +352,7 @@ library ValidationLogic { * @param assets The assets being flashborrowed * @param amounts The amounts for each asset being borrowed **/ - function validateFlashloan(address[] memory assets, uint256[] memory amounts) internal pure { + function validateFlashloan(address[] memory assets, uint256[] memory amounts) external pure { require(assets.length == amounts.length, Errors.VL_INCONSISTENT_FLASHLOAN_PARAMS); } From 099b1f0b054127d214e2e5bbe5f5d2dcb7c7a558 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 25 May 2021 11:22:58 +0200 Subject: [PATCH 30/34] fix: from 48 to 36 bits caps, added memory lib getters for caps --- .../configuration/ReserveConfiguration.sol | 58 ++++++++++++------- helpers/constants.ts | 4 +- markets/matic/reservesConfigs.ts | 2 + 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol index 77375778..567ee93b 100644 --- a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol @@ -19,8 +19,8 @@ library ReserveConfiguration { uint256 constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore - uint256 constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore - uint256 constant SUPPLY_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 constant SUPPLY_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // 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; @@ -32,15 +32,15 @@ library ReserveConfiguration { uint256 constant STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59; uint256 constant RESERVE_FACTOR_START_BIT_POSITION = 64; uint256 constant BORROW_CAP_START_BIT_POSITION = 80; - uint256 constant SUPPLY_CAP_START_BIT_POSITION = 128; + uint256 constant SUPPLY_CAP_START_BIT_POSITION = 116; uint256 constant MAX_VALID_LTV = 65535; uint256 constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535; uint256 constant MAX_VALID_LIQUIDATION_BONUS = 65535; uint256 constant MAX_VALID_DECIMALS = 255; uint256 constant MAX_VALID_RESERVE_FACTOR = 65535; - uint256 constant MAX_VALID_BORROW_CAP = 281474976710655; - uint256 constant MAX_VALID_SUPPLY_CAP = 281474976710655; + uint256 constant MAX_VALID_BORROW_CAP = 68719476735; + uint256 constant MAX_VALID_SUPPLY_CAP = 68719476735; /** * @dev Sets the Loan to Value of the reserve @@ -281,9 +281,7 @@ library ReserveConfiguration { { require(borrowCap <= MAX_VALID_BORROW_CAP, Errors.RC_INVALID_BORROW_CAP); - self.data = - (self.data & BORROW_CAP_MASK) | - (borrowCap << BORROW_CAP_START_BIT_POSITION); + self.data = (self.data & BORROW_CAP_MASK) | (borrowCap << BORROW_CAP_START_BIT_POSITION); } /** @@ -310,9 +308,7 @@ library ReserveConfiguration { { require(supplyCap <= MAX_VALID_SUPPLY_CAP, Errors.RC_INVALID_SUPPLY_CAP); - self.data = - (self.data & SUPPLY_CAP_MASK) | - (supplyCap << SUPPLY_CAP_START_BIT_POSITION); + self.data = (self.data & SUPPLY_CAP_MASK) | (supplyCap << SUPPLY_CAP_START_BIT_POSITION); } /** @@ -388,16 +384,13 @@ library ReserveConfiguration { function getCaps(DataTypes.ReserveConfigurationMap storage self) internal view - returns ( - uint256, - uint256 - ) + returns (uint256, uint256) { uint256 dataLocal = self.data; return ( - (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION, - (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION + (dataLocal & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION, + (dataLocal & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION ); } @@ -434,10 +427,7 @@ library ReserveConfiguration { function getCapsMemory(DataTypes.ReserveConfigurationMap memory self) internal pure - returns ( - uint256, - uint256 - ) + returns (uint256, uint256) { return ( (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION, @@ -467,4 +457,30 @@ library ReserveConfiguration { (self.data & ~STABLE_BORROWING_MASK) != 0 ); } + + /** + * @dev Gets the supply cap of the reserve from a memory objet + * @param self The reserve configuration + * @return The supply cap + **/ + function getSupplyCapMemory(DataTypes.ReserveConfigurationMap memory self) + internal + pure + returns (uint256) + { + return (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION; + } + + /** + * @dev Gets the borrow cap of the reserve from a memory object + * @param self The reserve configuration + * @return The borrow cap + **/ + function getBorrowCapMemory(DataTypes.ReserveConfigurationMap memory self) + internal + pure + returns (uint256) + { + return (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION; + } } diff --git a/helpers/constants.ts b/helpers/constants.ts index a0274bcc..f2568ee0 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -15,8 +15,8 @@ export const oneEther = new BigNumber(Math.pow(10, 18)); export const oneRay = new BigNumber(Math.pow(10, 27)); export const MAX_UINT_AMOUNT = '115792089237316195423570985008687907853269984665640564039457584007913129639935'; -export const MAX_BORROW_CAP = '281474976710655'; -export const MAX_SUPPLY_CAP = '281474976710655'; +export const MAX_BORROW_CAP = '68719476735'; +export const MAX_SUPPLY_CAP = '68719476735'; export const ONE_YEAR = '31536000'; export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; export const ONE_ADDRESS = '0x0000000000000000000000000000000000000001'; diff --git a/markets/matic/reservesConfigs.ts b/markets/matic/reservesConfigs.ts index 2fd924f1..a9f7f29f 100644 --- a/markets/matic/reservesConfigs.ts +++ b/markets/matic/reservesConfigs.ts @@ -90,6 +90,8 @@ export const strategyMATIC: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, + borrowCap: MAX_BORROW_CAP, + supplyCap: MAX_SUPPLY_CAP, reserveFactor: '2000', }; From 5b9dc19b691df609363bcd023a03003ea2dd88e9 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 25 May 2021 11:24:18 +0200 Subject: [PATCH 31/34] fix: fixed small naming/erros in tests --- test-suites/test-aave/borrow-cap.spec.ts | 4 ++-- test-suites/test-aave/configurator.spec.ts | 13 +++++++++---- test-suites/test-amm/configurator.spec.ts | 1 - 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/test-suites/test-aave/borrow-cap.spec.ts b/test-suites/test-aave/borrow-cap.spec.ts index 3b2a894c..5e03dfec 100644 --- a/test-suites/test-aave/borrow-cap.spec.ts +++ b/test-suites/test-aave/borrow-cap.spec.ts @@ -50,8 +50,8 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; expect(usdcBorrowCap).to.be.equal(MAX_BORROW_CAP); expect(daiBorrowCap).to.be.equal(MAX_BORROW_CAP); - let wethBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; - let wethSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + let wethBorrowCap = (await helpersContract.getReserveCaps(weth.address)).borrowCap; + let wethSupplyCap = (await helpersContract.getReserveCaps(weth.address)).supplyCap; expect(wethBorrowCap).to.be.equal(MAX_BORROW_CAP); expect(wethSupplyCap).to.be.equal(MAX_SUPPLY_CAP); diff --git a/test-suites/test-aave/configurator.spec.ts b/test-suites/test-aave/configurator.spec.ts index d4e3d0f1..929c56ea 100644 --- a/test-suites/test-aave/configurator.spec.ts +++ b/test-suites/test-aave/configurator.spec.ts @@ -1,5 +1,10 @@ import { TestEnv, makeSuite } from './helpers/make-suite'; -import { APPROVAL_AMOUNT_LENDING_POOL, MAX_UINT_AMOUNT, RAY, MAX_BORROW_CAP } from '../../helpers/constants'; +import { + APPROVAL_AMOUNT_LENDING_POOL, + MAX_UINT_AMOUNT, + RAY, + MAX_BORROW_CAP, +} from '../../helpers/constants'; import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; import { ProtocolErrors } from '../../helpers/types'; import { strategyWETH } from '../../markets/aave/reservesConfigs'; @@ -413,14 +418,14 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(reserveFactor).to.be.equal(1000); }); - it('Fails to change to too high borrowCap', async () => { + it('Check that borrowCap cannot be set to value that exceeds the MAX_BORROW_CAP', async () => { const { configurator, users, weth } = testEnv; await expect( configurator.setBorrowCap(weth.address, BigNumber.from(MAX_BORROW_CAP).add(1)), CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(RC_INVALID_BORROW_CAP); }); - it('Fails to change to too high supplyCap', async () => { + it('Check that supplyCap cannot be set to value that exceeds the MAX_SUPPLY_CAP', async () => { const { configurator, users, weth } = testEnv; await expect( configurator.setSupplyCap(weth.address, BigNumber.from(MAX_BORROW_CAP).add(1)), @@ -457,7 +462,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); - it('Changes the borrow Cap of WETH', async () => { + it('Changes the supply Cap of WETH', async () => { const { configurator, helpersContract, weth } = testEnv; await configurator.setSupplyCap(weth.address, '3000000'); const { diff --git a/test-suites/test-amm/configurator.spec.ts b/test-suites/test-amm/configurator.spec.ts index 4ba20620..d54abb78 100644 --- a/test-suites/test-amm/configurator.spec.ts +++ b/test-suites/test-amm/configurator.spec.ts @@ -180,7 +180,6 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(true /*strategyWETH.stableBorrowRateEnabled*/); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); - expect(variableBorrowIndex.toString()).to.be.equal(RAY); }); From f30d5baf8ed3fa965e374f537a73fa18c361ea4d Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 25 May 2021 13:37:24 +0200 Subject: [PATCH 32/34] doc: updated docs for supply & borrow caps, 48 -> 36 bits --- contracts/protocol/libraries/types/DataTypes.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/protocol/libraries/types/DataTypes.sol b/contracts/protocol/libraries/types/DataTypes.sol index 419efe59..5c620eaa 100644 --- a/contracts/protocol/libraries/types/DataTypes.sol +++ b/contracts/protocol/libraries/types/DataTypes.sol @@ -38,8 +38,8 @@ library DataTypes { //bit 59: stable rate borrowing enabled //bit 60-63: reserved //bit 64-79: reserve factor - //bit 80-127 borrow cap - //bit 128-175 borrow cap + //bit 80-115 borrow cap, borrowCap == 0 => disabled + //bit 116-152 supply cap, supplyCap == 0 => disabled uint256 data; } From 62f3f47b8470ee748cba237f205873ad4bdbddba Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 25 May 2021 14:20:09 +0200 Subject: [PATCH 33/34] feat: supply cap now by default disabled --- .../libraries/logic/ValidationLogic.sol | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index 08cffe5c..0c0b7028 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -44,13 +44,15 @@ library ValidationLogic { DataTypes.ReserveConfigurationMap memory reserveConfiguration = reserve.configuration; (bool isActive, bool isFrozen, , ) = reserveConfiguration.getFlagsMemory(); (, , , uint256 reserveDecimals, ) = reserveConfiguration.getParamsMemory(); + uint256 supplyCap = reserveConfiguration.getSupplyCapMemory(); require(amount != 0, Errors.VL_INVALID_AMOUNT); require(isActive, Errors.VL_NO_ACTIVE_RESERVE); require(!isFrozen, Errors.VL_RESERVE_FROZEN); require( - IERC20(reserve.aTokenAddress).totalSupply().add(amount).div(10**reserveDecimals) < - reserveConfiguration.getSupplyCapMemory(), + supplyCap == 0 || + IERC20(reserve.aTokenAddress).totalSupply().add(amount).div(10**reserveDecimals) < + supplyCap, Errors.VL_SUPPLY_CAP_EXCEEDED ); } @@ -84,6 +86,7 @@ library ValidationLogic { uint256 totalSupplyStableDebt; uint256 totalSupplyVariableDebt; uint256 reserveDecimals; + uint256 borrowCap; bool isActive; bool isFrozen; bool borrowingEnabled; @@ -145,13 +148,15 @@ library ValidationLogic { ); vars.totalSupplyStableDebt = IERC20(reserve.stableDebtTokenAddress).totalSupply(); - + vars.borrowCap = reserveConfiguration.getBorrowCapMemory(); vars.totalSupplyVariableDebt = IERC20(reserve.variableDebtTokenAddress).totalSupply(); require( - vars.totalSupplyStableDebt.add(vars.totalSupplyVariableDebt).add(amount).div( - 10**vars.reserveDecimals - ) < reserveConfiguration.getBorrowCapMemory(), + vars.borrowCap == 0 || + vars.totalSupplyStableDebt.add(vars.totalSupplyVariableDebt).add(amount).div( + 10**vars.reserveDecimals + ) < + vars.borrowCap, Errors.VL_BORROW_CAP_EXCEEDED ); From 4b256f1c257a894b65585579ea9494727c6942a7 Mon Sep 17 00:00:00 2001 From: Hadrien Charlanes Date: Tue, 25 May 2021 14:39:19 +0200 Subject: [PATCH 34/34] refactor: updated configs and tests for feat caps disabled by default --- markets/aave/reservesConfigs.ts | 85 +++++---- markets/amm/reservesConfigs.ts | 92 +++++----- markets/matic/reservesConfigs.ts | 29 ++- test-suites/test-aave/borrow-cap.spec.ts | 174 ++++++++++-------- test-suites/test-aave/configurator.spec.ts | 6 +- test-suites/test-aave/supply-cap.spec.ts | 197 ++++++++++++--------- 6 files changed, 316 insertions(+), 267 deletions(-) diff --git a/markets/aave/reservesConfigs.ts b/markets/aave/reservesConfigs.ts index c0be1118..f44e4dc8 100644 --- a/markets/aave/reservesConfigs.ts +++ b/markets/aave/reservesConfigs.ts @@ -1,4 +1,3 @@ -import { MAX_BORROW_CAP, MAX_SUPPLY_CAP } from '../../helpers/constants'; import { eContractid, IReserveParams } from '../../helpers/types'; import { @@ -23,8 +22,8 @@ export const strategyBUSD: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyDAI: IReserveParams = { @@ -37,8 +36,8 @@ export const strategyDAI: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategySUSD: IReserveParams = { @@ -51,8 +50,8 @@ export const strategySUSD: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyTUSD: IReserveParams = { @@ -65,8 +64,8 @@ export const strategyTUSD: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDC: IReserveParams = { @@ -79,8 +78,8 @@ export const strategyUSDC: IReserveParams = { reserveDecimals: '6', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDT: IReserveParams = { @@ -93,8 +92,8 @@ export const strategyUSDT: IReserveParams = { reserveDecimals: '6', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyAAVE: IReserveParams = { @@ -107,8 +106,8 @@ export const strategyAAVE: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '0', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyBAT: IReserveParams = { @@ -121,8 +120,8 @@ export const strategyBAT: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyENJ: IReserveParams = { @@ -135,8 +134,8 @@ export const strategyENJ: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyWETH: IReserveParams = { @@ -149,8 +148,8 @@ export const strategyWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyKNC: IReserveParams = { @@ -163,8 +162,8 @@ export const strategyKNC: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyLINK: IReserveParams = { @@ -177,8 +176,8 @@ export const strategyLINK: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyMANA: IReserveParams = { @@ -191,8 +190,8 @@ export const strategyMANA: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '3500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyMKR: IReserveParams = { @@ -205,8 +204,8 @@ export const strategyMKR: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyREN: IReserveParams = { @@ -219,8 +218,8 @@ export const strategyREN: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategySNX: IReserveParams = { @@ -233,8 +232,8 @@ export const strategySNX: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '3500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; // Invalid borrow rates in params currently, replaced with snx params @@ -248,8 +247,8 @@ export const strategyUNI: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.DelegationAwareAToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyWBTC: IReserveParams = { @@ -262,8 +261,8 @@ export const strategyWBTC: IReserveParams = { reserveDecimals: '8', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyYFI: IReserveParams = { @@ -276,8 +275,8 @@ export const strategyYFI: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyZRX: IReserveParams = { @@ -290,8 +289,8 @@ export const strategyZRX: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyXSUSHI: IReserveParams = { @@ -304,6 +303,6 @@ export const strategyXSUSHI: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '3500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; diff --git a/markets/amm/reservesConfigs.ts b/markets/amm/reservesConfigs.ts index 8f0f06fa..d59f9ad6 100644 --- a/markets/amm/reservesConfigs.ts +++ b/markets/amm/reservesConfigs.ts @@ -1,11 +1,5 @@ -import { MAX_BORROW_CAP, MAX_SUPPLY_CAP } from '../../helpers/constants'; -import { eContractid, IReserveParams} from '../../helpers/types'; -import { - rateStrategyAmmBase, - rateStrategyStable, - rateStrategyBaseOne, -} from './rateStrategies'; - +import { eContractid, IReserveParams } from '../../helpers/types'; +import { rateStrategyAmmBase, rateStrategyStable, rateStrategyBaseOne } from './rateStrategies'; export const strategyWETH: IReserveParams = { strategy: rateStrategyBaseOne, @@ -17,8 +11,8 @@ export const strategyWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyWBTC: IReserveParams = { @@ -31,8 +25,8 @@ export const strategyWBTC: IReserveParams = { reserveDecimals: '8', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyDAI: IReserveParams = { @@ -45,8 +39,8 @@ export const strategyDAI: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDC: IReserveParams = { @@ -59,8 +53,8 @@ export const strategyUSDC: IReserveParams = { reserveDecimals: '6', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDT: IReserveParams = { @@ -73,8 +67,8 @@ export const strategyUSDT: IReserveParams = { reserveDecimals: '6', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyDAIWETH: IReserveParams = { @@ -87,8 +81,8 @@ export const strategyDAIWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyWBTCWETH: IReserveParams = { @@ -101,8 +95,8 @@ export const strategyWBTCWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyAAVEWETH: IReserveParams = { @@ -115,8 +109,8 @@ export const strategyAAVEWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyBATWETH: IReserveParams = { @@ -129,8 +123,8 @@ export const strategyBATWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyDAIUSDC: IReserveParams = { @@ -143,8 +137,8 @@ export const strategyDAIUSDC: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyCRVWETH: IReserveParams = { @@ -157,8 +151,8 @@ export const strategyCRVWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyLINKWETH: IReserveParams = { @@ -171,8 +165,8 @@ export const strategyLINKWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyMKRWETH: IReserveParams = { @@ -185,8 +179,8 @@ export const strategyMKRWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyRENWETH: IReserveParams = { @@ -199,8 +193,8 @@ export const strategyRENWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategySNXWETH: IReserveParams = { @@ -213,8 +207,8 @@ export const strategySNXWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyUNIWETH: IReserveParams = { @@ -227,8 +221,8 @@ export const strategyUNIWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDCWETH: IReserveParams = { @@ -241,8 +235,8 @@ export const strategyUSDCWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyWBTCUSDC: IReserveParams = { @@ -255,8 +249,8 @@ export const strategyWBTCUSDC: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyYFIWETH: IReserveParams = { @@ -269,8 +263,8 @@ export const strategyYFIWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyBALWETH: IReserveParams = { @@ -283,6 +277,6 @@ export const strategyBALWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1500', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, -} \ No newline at end of file + borrowCap: '0', + supplyCap: '0', +}; diff --git a/markets/matic/reservesConfigs.ts b/markets/matic/reservesConfigs.ts index a9f7f29f..cbeba1a6 100644 --- a/markets/matic/reservesConfigs.ts +++ b/markets/matic/reservesConfigs.ts @@ -1,6 +1,5 @@ // import BigNumber from 'bignumber.js'; // import { oneRay } from '../../helpers/constants'; -import { MAX_BORROW_CAP, MAX_SUPPLY_CAP } from '../../helpers/constants'; import { eContractid, IReserveParams } from '../../helpers/types'; import { rateStrategyStableTwo, @@ -21,8 +20,8 @@ export const strategyDAI: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDC: IReserveParams = { @@ -35,8 +34,8 @@ export const strategyUSDC: IReserveParams = { reserveDecimals: '6', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDT: IReserveParams = { @@ -49,8 +48,8 @@ export const strategyUSDT: IReserveParams = { reserveDecimals: '6', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyWETH: IReserveParams = { @@ -63,8 +62,8 @@ export const strategyWETH: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '1000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyWBTC: IReserveParams = { @@ -77,8 +76,8 @@ export const strategyWBTC: IReserveParams = { reserveDecimals: '8', aTokenImpl: eContractid.AToken, reserveFactor: '2000', - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', }; export const strategyMATIC: IReserveParams = { @@ -90,8 +89,8 @@ export const strategyMATIC: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', reserveFactor: '2000', }; @@ -104,7 +103,7 @@ export const strategyAAVE: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - borrowCap: MAX_BORROW_CAP, - supplyCap: MAX_SUPPLY_CAP, + borrowCap: '0', + supplyCap: '0', reserveFactor: '0', }; diff --git a/test-suites/test-aave/borrow-cap.spec.ts b/test-suites/test-aave/borrow-cap.spec.ts index 5e03dfec..15dd0a4d 100644 --- a/test-suites/test-aave/borrow-cap.spec.ts +++ b/test-suites/test-aave/borrow-cap.spec.ts @@ -16,10 +16,9 @@ const { expect } = require('chai'); makeSuite('Borrow Cap', (testEnv: TestEnv) => { const { VL_BORROW_CAP_EXCEEDED, RC_INVALID_BORROW_CAP } = ProtocolErrors; - const miliUnitToPrecision = async (token: WETH9Mocked | MintableERC20, nb: string) => + const unitParse = async (token: WETH9Mocked | MintableERC20, nb: string) => BigNumber.from(nb).mul(BigNumber.from('10').pow((await token.decimals()) - 3)); - - it('Sets the borrow cap for Weth and DAI to 0 Units, deposits weth', async () => { + it('Reserves should initially have borrow cap disabled (borrowCap = 0)', async () => { const { configurator, weth, @@ -30,61 +29,111 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { helpersContract, users: [user1], } = testEnv; - const mintedMiliAmount = '1000000000000'; - const daiMinted = await miliUnitToPrecision(dai, mintedMiliAmount); - const wethMinted = await miliUnitToPrecision(weth, mintedMiliAmount); - const usdcMinted = await miliUnitToPrecision(usdc, mintedMiliAmount); - await dai.mint(daiMinted); - await weth.mint(wethMinted); - await usdc.mint(usdcMinted); - await dai.connect(user1.signer).mint(daiMinted); - await weth.connect(user1.signer).mint(wethMinted); - await usdc.connect(user1.signer).mint(usdcMinted); + + 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); + let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; - expect(usdcBorrowCap).to.be.equal(MAX_BORROW_CAP); - expect(daiBorrowCap).to.be.equal(MAX_BORROW_CAP); - let wethBorrowCap = (await helpersContract.getReserveCaps(weth.address)).borrowCap; - let wethSupplyCap = (await helpersContract.getReserveCaps(weth.address)).supplyCap; - expect(wethBorrowCap).to.be.equal(MAX_BORROW_CAP); - expect(wethSupplyCap).to.be.equal(MAX_SUPPLY_CAP); - const depositedMiliAmount = (1e9).toString(); + expect(usdcBorrowCap).to.be.equal('0'); + expect(daiBorrowCap).to.be.equal('0'); + }); + it('Should be able to borrow 10 Dai stable, 10 USDC variable', async () => { + const { + configurator, + weth, + pool, + dai, + usdc, + deployer, + helpersContract, + users: [user1], + } = testEnv; - await configurator.setBorrowCap(usdc.address, 0); - await configurator.setBorrowCap(dai.address, 0); + const suppliedAmount = 1000; + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); - usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; - daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; - - expect(usdcBorrowCap).to.be.equal(0); - expect(daiBorrowCap).to.be.equal(0); + const borrowedAmount = 10; + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); + // deposit collateral await pool.deposit( weth.address, - await miliUnitToPrecision(weth, depositedMiliAmount), + await unitParse(weth, precisionSuppliedAmount), deployer.address, 0 ); - await pool.connect(user1.signer).deposit(weth.address, wethMinted, user1.address, 0); - await pool.connect(user1.signer).deposit(dai.address, daiMinted, user1.address, 0); - await pool.connect(user1.signer).deposit(usdc.address, usdcMinted, user1.address, 0); + // user 1 deposit more dai and usdc to be able to borrow + await pool + .connect(user1.signer) + .deposit(dai.address, await unitParse(dai, precisionSuppliedAmount), user1.address, 0); + + await pool + .connect(user1.signer) + .deposit(usdc.address, await unitParse(usdc, precisionSuppliedAmount), user1.address, 0); + + // borrow + await pool.borrow( + usdc.address, + await unitParse(usdc, precisionBorrowedAmount), + 2, + 0, + deployer.address + ); + + await pool.borrow( + dai.address, + await unitParse(dai, precisionBorrowedAmount), + 1, + 0, + deployer.address + ); + }); + it('Sets the borrow cap for Weth and DAI to 10 Units', async () => { + const { + configurator, + weth, + pool, + dai, + usdc, + deployer, + helpersContract, + users: [user1], + } = testEnv; + + await configurator.setBorrowCap(usdc.address, 10); + await configurator.setBorrowCap(dai.address, 10); + + const usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + const daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; + + expect(usdcBorrowCap).to.be.equal(10); + expect(daiBorrowCap).to.be.equal(10); }); it('should fail to borrow any dai or usdc, stable or variable', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const borrowedAmount = 10; - const borrowedMilimount = (borrowedAmount * 1000).toString(); + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); await expect( pool.borrow( usdc.address, - await miliUnitToPrecision(usdc, borrowedMilimount), + await unitParse(usdc, precisionBorrowedAmount), 2, 0, deployer.address @@ -94,7 +143,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { await expect( pool.borrow( dai.address, - await miliUnitToPrecision(dai, borrowedMilimount), + await unitParse(dai, precisionBorrowedAmount), 2, 0, deployer.address @@ -104,11 +153,6 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { it('Should fail to set the borrow cap for usdc and DAI to max cap + 1 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; const newCap = Number(MAX_BORROW_CAP) + 1; - let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; - let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; - - expect(usdcBorrowCap).to.be.equal(0); - expect(daiBorrowCap).to.be.equal(0); await expect(configurator.setBorrowCap(usdc.address, newCap)).to.be.revertedWith( RC_INVALID_BORROW_CAP @@ -116,24 +160,16 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { await expect(configurator.setBorrowCap(dai.address, newCap)).to.be.revertedWith( RC_INVALID_BORROW_CAP ); - - usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; - daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; }); - it('Sets the borrow cap for usdc and DAI to 110 Units', async () => { + it('Sets the borrow cap for usdc and DAI to 120 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; - const newCap = '110'; - let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; - let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; - - expect(usdcBorrowCap).to.be.equal(0); - expect(daiBorrowCap).to.be.equal(0); + const newCap = '120'; await configurator.setBorrowCap(usdc.address, newCap); await configurator.setBorrowCap(dai.address, newCap); - usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; - daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; + const usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + const daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; expect(usdcBorrowCap).to.be.equal(newCap); expect(daiBorrowCap).to.be.equal(newCap); @@ -141,10 +177,10 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { it('Should succeed to borrow 10 stable dai and 10 variable usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const borrowedAmount = 10; - const borrowedMilimount = (borrowedAmount * 1000).toString(); + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); await pool.borrow( usdc.address, - await miliUnitToPrecision(usdc, borrowedMilimount), + await unitParse(usdc, precisionBorrowedAmount), 2, 0, deployer.address @@ -152,7 +188,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { await pool.borrow( dai.address, - await miliUnitToPrecision(dai, borrowedMilimount), + await unitParse(dai, precisionBorrowedAmount), 1, 0, deployer.address @@ -161,12 +197,12 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { it('should fail to borrow 100 variable dai and 100 stable usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const borrowedAmount = 100; - const borrowedMilimount = (borrowedAmount * 1000).toString(); + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); await expect( pool.borrow( usdc.address, - await miliUnitToPrecision(usdc, borrowedMilimount), + await unitParse(usdc, precisionBorrowedAmount), 1, 0, deployer.address @@ -176,7 +212,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { await expect( pool.borrow( dai.address, - await miliUnitToPrecision(dai, borrowedMilimount), + await unitParse(dai, precisionBorrowedAmount), 2, 0, deployer.address @@ -186,10 +222,10 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { it('Should succeed to borrow 99 variable dai and 99 stable usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const borrowedAmount = 99; - const borrowedMilimount = (borrowedAmount * 1000).toString(); + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); await pool.borrow( usdc.address, - await miliUnitToPrecision(usdc, borrowedMilimount), + await unitParse(usdc, precisionBorrowedAmount), 2, 0, deployer.address @@ -197,7 +233,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { await pool.borrow( dai.address, - await miliUnitToPrecision(dai, borrowedMilimount), + await unitParse(dai, precisionBorrowedAmount), 1, 0, deployer.address @@ -221,11 +257,11 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { it('should succeed to borrow 100 variable dai and 100 stable usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const borrowedAmount = 100; - const borrowedMilimount = (borrowedAmount * 1000).toString(); + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); await pool.borrow( usdc.address, - await miliUnitToPrecision(usdc, borrowedMilimount), + await unitParse(usdc, precisionBorrowedAmount), 1, 0, deployer.address @@ -233,7 +269,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { await pool.borrow( dai.address, - await miliUnitToPrecision(dai, borrowedMilimount), + await unitParse(dai, precisionBorrowedAmount), 2, 0, deployer.address @@ -257,12 +293,12 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { it('should fail to borrow 100 variable dai and 100 stable usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const borrowedAmount = 100; - const borrowedMilimount = (borrowedAmount * 1000).toString(); + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); await expect( pool.borrow( usdc.address, - await miliUnitToPrecision(usdc, borrowedMilimount), + await unitParse(usdc, precisionBorrowedAmount), 1, 0, deployer.address @@ -272,7 +308,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { await expect( pool.borrow( dai.address, - await miliUnitToPrecision(dai, borrowedMilimount), + await unitParse(dai, precisionBorrowedAmount), 2, 0, deployer.address @@ -297,11 +333,11 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { it('should succeed to borrow 100 variable dai and 100 stable usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const borrowedAmount = 100; - const borrowedMilimount = (borrowedAmount * 1000).toString(); + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); await pool.borrow( usdc.address, - await miliUnitToPrecision(usdc, borrowedMilimount), + await unitParse(usdc, precisionBorrowedAmount), 1, 0, deployer.address @@ -309,7 +345,7 @@ makeSuite('Borrow Cap', (testEnv: TestEnv) => { await pool.borrow( dai.address, - await miliUnitToPrecision(dai, borrowedMilimount), + await unitParse(dai, precisionBorrowedAmount), 2, 0, deployer.address diff --git a/test-suites/test-aave/configurator.spec.ts b/test-suites/test-aave/configurator.spec.ts index 929c56ea..d92779b5 100644 --- a/test-suites/test-aave/configurator.spec.ts +++ b/test-suites/test-aave/configurator.spec.ts @@ -173,7 +173,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { it('Activates the ETH reserve for borrowing', async () => { const { configurator, weth, helpersContract } = testEnv; - await configurator.enableBorrowingOnReserve(weth.address, MAX_BORROW_CAP, true); + await configurator.enableBorrowingOnReserve(weth.address, '0', true); const { variableBorrowIndex } = await helpersContract.getReserveData(weth.address); const { @@ -215,9 +215,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => { const { configurator, users, weth } = testEnv; await expect( - configurator - .connect(users[2].signer) - .enableBorrowingOnReserve(weth.address, MAX_BORROW_CAP, true), + configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, '0', true), CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); diff --git a/test-suites/test-aave/supply-cap.spec.ts b/test-suites/test-aave/supply-cap.spec.ts index 8c35d197..6c213682 100644 --- a/test-suites/test-aave/supply-cap.spec.ts +++ b/test-suites/test-aave/supply-cap.spec.ts @@ -15,10 +15,10 @@ const { expect } = require('chai'); makeSuite('supply Cap', (testEnv: TestEnv) => { const { VL_SUPPLY_CAP_EXCEEDED, RC_INVALID_SUPPLY_CAP } = ProtocolErrors; - const miliUnitToPrecision = async (token: WETH9Mocked | MintableERC20, nb: string) => + const unitParse = async (token: WETH9Mocked | MintableERC20, nb: string) => BigNumber.from(nb).mul(BigNumber.from('10').pow((await token.decimals()) - 3)); - it('Sets the supply cap for Weth and DAI to 0 Units, deposits weth', async () => { + it('Reserves should initially have supply cap disabled (supplyCap = 0)', async () => { const { configurator, weth, @@ -29,61 +29,101 @@ makeSuite('supply Cap', (testEnv: TestEnv) => { helpersContract, users: [user1], } = testEnv; + const mintedAmount = parseEther('1000000000'); await dai.mint(mintedAmount); await weth.mint(mintedAmount); await usdc.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); - let usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; - let daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; - expect(usdcsupplyCap).to.be.equal(MAX_SUPPLY_CAP); - expect(daisupplyCap).to.be.equal(MAX_SUPPLY_CAP); + let usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + let daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; - const depositedMiliAmount = (1e9).toString(); + expect(usdcSupplyCap).to.be.equal('0'); + expect(daiSupplyCap).to.be.equal('0'); + }); + it('Should be able to deposit 1000 Dai, 1000 USDC and 1000 Weth', async () => { + const { + configurator, + weth, + pool, + dai, + usdc, + deployer, + helpersContract, + users: [user1], + } = testEnv; - await configurator.setSupplyCap(usdc.address, 0); - await configurator.setSupplyCap(dai.address, 0); + const suppliedAmount = 1000; + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); - usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; - daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + await pool.deposit( + usdc.address, + await unitParse(usdc, precisionSuppliedAmount), + deployer.address, + 0 + ); - expect(usdcsupplyCap).to.be.equal(0); - expect(daisupplyCap).to.be.equal(0); + await pool.deposit( + dai.address, + await unitParse(dai, precisionSuppliedAmount), + deployer.address, + 0 + ); + await pool.deposit( + weth.address, + await unitParse(weth, precisionSuppliedAmount), + deployer.address, + 0 + ); + }); + it('Sets the supply cap for Weth and DAI to 1000 Unit', async () => { + const { + configurator, + weth, + pool, + dai, + usdc, + deployer, + helpersContract, + users: [user1], + } = testEnv; + + const newCap = '1000'; + + await configurator.setSupplyCap(usdc.address, newCap); + await configurator.setSupplyCap(dai.address, newCap); + + const usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + const daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcSupplyCap).to.be.equal(newCap); + expect(daiSupplyCap).to.be.equal(newCap); }); it('should fail to supply any dai or usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const suppliedAmount = 10; - const suppliedMilimount = (suppliedAmount * 1000).toString(); + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); await expect( pool.deposit( usdc.address, - await miliUnitToPrecision(usdc, suppliedMilimount), + await unitParse(usdc, precisionSuppliedAmount), deployer.address, 0 ) ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); await expect( - pool.deposit( - dai.address, - await miliUnitToPrecision(dai, suppliedMilimount), - deployer.address, - 0 - ) + pool.deposit(dai.address, await unitParse(dai, precisionSuppliedAmount), deployer.address, 0) ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); }); it('Should fail to set the supply cap for usdc and DAI to max cap + 1 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; const newCap = Number(MAX_SUPPLY_CAP) + 1; - let usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; - let daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; - - expect(usdcsupplyCap).to.be.equal(0); - expect(daisupplyCap).to.be.equal(0); await expect(configurator.setSupplyCap(usdc.address, newCap)).to.be.revertedWith( RC_INVALID_SUPPLY_CAP @@ -92,38 +132,33 @@ makeSuite('supply Cap', (testEnv: TestEnv) => { RC_INVALID_SUPPLY_CAP ); }); - it('Sets the supply cap for usdc and DAI to 110 Units', async () => { + it('Sets the supply cap for usdc and DAI to 1110 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; - const newCap = '110'; - let usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; - let daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; - - expect(usdcsupplyCap).to.be.equal(0); - expect(daisupplyCap).to.be.equal(0); + const newCap = '1110'; await configurator.setSupplyCap(usdc.address, newCap); await configurator.setSupplyCap(dai.address, newCap); - usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; - daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + const usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + const daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; - expect(usdcsupplyCap).to.be.equal(newCap); - expect(daisupplyCap).to.be.equal(newCap); + expect(usdcSupplyCap).to.be.equal(newCap); + expect(daiSupplyCap).to.be.equal(newCap); }); it('Should succeed to supply 10 dai and 10 usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const suppliedAmount = 10; - const suppliedMilimount = (suppliedAmount * 1000).toString(); + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); await pool.deposit( usdc.address, - await miliUnitToPrecision(usdc, suppliedMilimount), + await unitParse(usdc, precisionSuppliedAmount), deployer.address, 0 ); await pool.deposit( dai.address, - await miliUnitToPrecision(dai, suppliedMilimount), + await unitParse(dai, precisionSuppliedAmount), deployer.address, 0 ); @@ -131,144 +166,132 @@ makeSuite('supply Cap', (testEnv: TestEnv) => { it('should fail to supply 100 dai and 100 usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const suppliedAmount = 100; - const suppliedMilimount = (suppliedAmount * 1000).toString(); + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); await expect( pool.deposit( usdc.address, - await miliUnitToPrecision(usdc, suppliedMilimount), + await unitParse(usdc, precisionSuppliedAmount), deployer.address, 0 ) ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); await expect( - pool.deposit( - dai.address, - await miliUnitToPrecision(dai, suppliedMilimount), - deployer.address, - 0 - ) + pool.deposit(dai.address, await unitParse(dai, precisionSuppliedAmount), deployer.address, 0) ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); }); it('Should succeed to supply 99 dai and 99 usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const suppliedAmount = 99; - const suppliedMilimount = (suppliedAmount * 1000).toString(); + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); await pool.deposit( usdc.address, - await miliUnitToPrecision(usdc, suppliedMilimount), + await unitParse(usdc, precisionSuppliedAmount), deployer.address, 0 ); await pool.deposit( dai.address, - await miliUnitToPrecision(dai, suppliedMilimount), + await unitParse(dai, precisionSuppliedAmount), deployer.address, 0 ); }); - it('Raises the supply cap for usdc and DAI to 1000 Units', async () => { + it('Raises the supply cap for usdc and DAI to 2000 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; - const newCap = '1000'; - let usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; - let daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + const newCap = '2000'; await configurator.setSupplyCap(usdc.address, newCap); await configurator.setSupplyCap(dai.address, newCap); - usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; - daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + const usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + const daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; - expect(usdcsupplyCap).to.be.equal(newCap); - expect(daisupplyCap).to.be.equal(newCap); + expect(usdcSupplyCap).to.be.equal(newCap); + expect(daiSupplyCap).to.be.equal(newCap); }); it('should succeed to supply 100 dai and 100 usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const suppliedAmount = 100; - const suppliedMilimount = (suppliedAmount * 1000).toString(); + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); await pool.deposit( usdc.address, - await miliUnitToPrecision(usdc, suppliedMilimount), + await unitParse(usdc, precisionSuppliedAmount), deployer.address, 0 ); await pool.deposit( dai.address, - await miliUnitToPrecision(dai, suppliedMilimount), + await unitParse(dai, precisionSuppliedAmount), deployer.address, 0 ); }); - it('Lowers the supply cap for usdc and DAI to 200 Units', async () => { + it('Lowers the supply cap for usdc and DAI to 1200 Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; - const newCap = '200'; - let usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; - let daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + const newCap = '1200'; + let usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + let daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; await configurator.setSupplyCap(usdc.address, newCap); await configurator.setSupplyCap(dai.address, newCap); - usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; - daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; - expect(usdcsupplyCap).to.be.equal(newCap); - expect(daisupplyCap).to.be.equal(newCap); + expect(usdcSupplyCap).to.be.equal(newCap); + expect(daiSupplyCap).to.be.equal(newCap); }); it('should fail to supply 100 dai and 100 usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const suppliedAmount = 100; - const suppliedMilimount = (suppliedAmount * 1000).toString(); + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); await expect( pool.deposit( usdc.address, - await miliUnitToPrecision(usdc, suppliedMilimount), + await unitParse(usdc, precisionSuppliedAmount), deployer.address, 0 ) ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); await expect( - pool.deposit( - dai.address, - await miliUnitToPrecision(dai, suppliedMilimount), - deployer.address, - 0 - ) + pool.deposit(dai.address, await unitParse(dai, precisionSuppliedAmount), deployer.address, 0) ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); }); it('Raises the supply cap for usdc and DAI to max cap Units', async () => { const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; const newCap = MAX_SUPPLY_CAP; - let usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; - let daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + let usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + let daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; await configurator.setSupplyCap(usdc.address, newCap); await configurator.setSupplyCap(dai.address, newCap); - usdcsupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; - daisupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; - expect(usdcsupplyCap).to.be.equal(newCap); - expect(daisupplyCap).to.be.equal(newCap); + expect(usdcSupplyCap).to.be.equal(newCap); + expect(daiSupplyCap).to.be.equal(newCap); }); it('should succeed to supply 100 dai and 100 usdc', async () => { const { usdc, pool, dai, deployer, helpersContract } = testEnv; const suppliedAmount = 100; - const suppliedMilimount = (suppliedAmount * 1000).toString(); + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); await pool.deposit( usdc.address, - await miliUnitToPrecision(usdc, suppliedMilimount), + await unitParse(usdc, precisionSuppliedAmount), deployer.address, 0 ); await pool.deposit( dai.address, - await miliUnitToPrecision(dai, suppliedMilimount), + await unitParse(dai, precisionSuppliedAmount), deployer.address, 0 );