Merge pull request #95 from aave/feat/2.5-supply-and-borrow-caps

Feat/2.5 supply and borrow caps: aggregated
This commit is contained in:
The-3D 2021-05-27 12:38:48 +02:00 committed by GitHub
commit dbd255e952
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 1209 additions and 105 deletions

View File

@ -31,6 +31,8 @@ contract ATokensAndRatesHelper is Ownable {
uint256 liquidationThreshold; uint256 liquidationThreshold;
uint256 liquidationBonus; uint256 liquidationBonus;
uint256 reserveFactor; uint256 reserveFactor;
uint256 borrowCap;
uint256 supplyCap;
bool stableBorrowingEnabled; bool stableBorrowingEnabled;
bool borrowingEnabled; bool borrowingEnabled;
} }
@ -77,9 +79,11 @@ contract ATokensAndRatesHelper is Ownable {
if (inputParams[i].borrowingEnabled) { if (inputParams[i].borrowingEnabled) {
configurator.enableBorrowingOnReserve( configurator.enableBorrowingOnReserve(
inputParams[i].asset, inputParams[i].asset,
inputParams[i].borrowCap,
inputParams[i].stableBorrowingEnabled inputParams[i].stableBorrowingEnabled
); );
} }
configurator.setSupplyCap(inputParams[i].asset, inputParams[i].supplyCap);
configurator.setReserveFactor(inputParams[i].asset, inputParams[i].reserveFactor); configurator.setReserveFactor(inputParams[i].asset, inputParams[i].reserveFactor);
} }
} }

View File

@ -127,6 +127,20 @@ interface ILendingPoolConfigurator {
**/ **/
event ReserveFactorChanged(address indexed asset, uint256 factor); 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 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 * @dev Emitted when the reserve decimals are updated
* @param asset The address of the underlying asset of the reserve * @param asset The address of the underlying asset of the reserve

View File

@ -64,6 +64,7 @@ contract AaveProtocolDataProvider {
return aTokens; return aTokens;
} }
// not returning borrow and supply caps for compatibility
function getReserveConfigurationData(address asset) function getReserveConfigurationData(address asset)
external external
view view
@ -80,18 +81,28 @@ contract AaveProtocolDataProvider {
bool isFrozen bool isFrozen
) )
{ {
DataTypes.ReserveConfigurationMap memory configuration = DataTypes.ReserveConfigurationMap memory configuration =
ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getConfiguration(asset); ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getConfiguration(asset);
(ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor) = configuration (ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor) =
.getParamsMemory(); configuration.getParamsMemory();
(isActive, isFrozen, borrowingEnabled, stableBorrowRateEnabled) = configuration (isActive, isFrozen, borrowingEnabled, stableBorrowRateEnabled) =
.getFlagsMemory(); configuration.getFlagsMemory();
usageAsCollateralEnabled = liquidationThreshold > 0; usageAsCollateralEnabled = liquidationThreshold > 0;
} }
function getReserveCaps(address asset)
external
view
returns (uint256 borrowCap, uint256 supplyCap) {
(borrowCap, supplyCap) = ILendingPool(ADDRESSES_PROVIDER.getLendingPool())
.getConfiguration(asset)
.getCapsMemory();
}
function getReserveData(address asset) function getReserveData(address asset)
external external
view view

View File

@ -114,6 +114,10 @@ contract UiPoolDataProvider is IUiPoolDataProvider {
reserveData.decimals, reserveData.decimals,
reserveData.reserveFactor reserveData.reserveFactor
) = baseData.configuration.getParamsMemory(); ) = baseData.configuration.getParamsMemory();
(
reserveData.borrowCap,
reserveData.supplyCap
) = baseData.configuration.getCapsMemory();
( (
reserveData.isActive, reserveData.isActive,
reserveData.isFrozen, reserveData.isFrozen,

View File

@ -15,6 +15,8 @@ interface IUiPoolDataProvider {
uint256 reserveLiquidationThreshold; uint256 reserveLiquidationThreshold;
uint256 reserveLiquidationBonus; uint256 reserveLiquidationBonus;
uint256 reserveFactor; uint256 reserveFactor;
uint256 borrowCap;
uint256 supplyCap;
bool usageAsCollateralEnabled; bool usageAsCollateralEnabled;
bool borrowingEnabled; bool borrowingEnabled;
bool stableBorrowRateEnabled; bool stableBorrowRateEnabled;

View File

@ -151,7 +151,8 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory();
bytes memory encodedCall = abi.encodeWithSelector( bytes memory encodedCall =
abi.encodeWithSelector(
IInitializableAToken.initialize.selector, IInitializableAToken.initialize.selector,
cachedPool, cachedPool,
input.treasury, input.treasury,
@ -163,11 +164,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
input.params input.params
); );
_upgradeTokenImplementation( _upgradeTokenImplementation(reserveData.aTokenAddress, input.implementation, encodedCall);
reserveData.aTokenAddress,
input.implementation,
encodedCall
);
emit ATokenUpgraded(input.asset, reserveData.aTokenAddress, input.implementation); emit ATokenUpgraded(input.asset, reserveData.aTokenAddress, input.implementation);
} }
@ -179,10 +176,11 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
ILendingPool cachedPool = pool; ILendingPool cachedPool = pool;
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); 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( bytes memory encodedCall =
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector, IInitializableDebtToken.initialize.selector,
cachedPool, cachedPool,
input.asset, input.asset,
@ -209,17 +207,15 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
/** /**
* @dev Updates the variable debt token implementation for the asset * @dev Updates the variable debt token implementation for the asset
**/ **/
function updateVariableDebtToken(UpdateDebtTokenInput calldata input) function updateVariableDebtToken(UpdateDebtTokenInput calldata input) external onlyPoolAdmin {
external
onlyPoolAdmin
{
ILendingPool cachedPool = pool; ILendingPool cachedPool = pool;
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); 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( bytes memory encodedCall =
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector, IInitializableDebtToken.initialize.selector,
cachedPool, cachedPool,
input.asset, input.asset,
@ -248,17 +244,20 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
* @param asset The address of the underlying asset of the reserve * @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 * @param stableBorrowRateEnabled True if stable borrow rate needs to be enabled by default on this reserve
**/ **/
function enableBorrowingOnReserve(address asset, bool stableBorrowRateEnabled) function enableBorrowingOnReserve(
external address asset,
onlyPoolAdmin uint256 borrowCap,
{ bool stableBorrowRateEnabled
) external onlyPoolAdmin {
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
currentConfig.setBorrowingEnabled(true); currentConfig.setBorrowingEnabled(true);
currentConfig.setBorrowCap(borrowCap);
currentConfig.setStableRateBorrowingEnabled(stableBorrowRateEnabled); currentConfig.setStableRateBorrowingEnabled(stableBorrowRateEnabled);
pool.setConfiguration(asset, currentConfig.data); pool.setConfiguration(asset, currentConfig.data);
emit BorrowCapChanged(asset, borrowCap);
emit BorrowingEnabledOnReserve(asset, stableBorrowRateEnabled); emit BorrowingEnabledOnReserve(asset, stableBorrowRateEnabled);
} }
@ -430,6 +429,36 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
emit ReserveFactorChanged(asset, reserveFactor); 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 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 * @dev Sets the interest rate strategy of a reserve
* @param asset The address of the underlying asset of the reserve * @param asset The address of the underlying asset of the reserve

View File

@ -19,6 +19,8 @@ library ReserveConfiguration {
uint256 constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore uint256 constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore
uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore
uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // 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 /// @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; uint256 constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16;
@ -29,12 +31,16 @@ library ReserveConfiguration {
uint256 constant BORROWING_ENABLED_START_BIT_POSITION = 58; uint256 constant BORROWING_ENABLED_START_BIT_POSITION = 58;
uint256 constant STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59; uint256 constant STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59;
uint256 constant RESERVE_FACTOR_START_BIT_POSITION = 64; uint256 constant RESERVE_FACTOR_START_BIT_POSITION = 64;
uint256 constant BORROW_CAP_START_BIT_POSITION = 80;
uint256 constant SUPPLY_CAP_START_BIT_POSITION = 116;
uint256 constant MAX_VALID_LTV = 65535; uint256 constant MAX_VALID_LTV = 65535;
uint256 constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535; uint256 constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535;
uint256 constant MAX_VALID_LIQUIDATION_BONUS = 65535; uint256 constant MAX_VALID_LIQUIDATION_BONUS = 65535;
uint256 constant MAX_VALID_DECIMALS = 255; uint256 constant MAX_VALID_DECIMALS = 255;
uint256 constant MAX_VALID_RESERVE_FACTOR = 65535; uint256 constant MAX_VALID_RESERVE_FACTOR = 65535;
uint256 constant MAX_VALID_BORROW_CAP = 68719476735;
uint256 constant MAX_VALID_SUPPLY_CAP = 68719476735;
/** /**
* @dev Sets the Loan to Value of the reserve * @dev Sets the Loan to Value of the reserve
@ -264,6 +270,60 @@ library ReserveConfiguration {
return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION; 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 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 * @dev Gets the configuration flags of the reserve
* @param self The reserve configuration * @param self The reserve configuration
@ -290,9 +350,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 * @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
**/ **/
function getParams(DataTypes.ReserveConfigurationMap storage self) function getParams(DataTypes.ReserveConfigurationMap storage self)
internal internal
@ -316,10 +376,28 @@ library ReserveConfiguration {
); );
} }
/**
* @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 (
(dataLocal & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION,
(dataLocal & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION
);
}
/** /**
* @dev Gets the configuration paramters of the reserve from a memory object * @dev Gets the configuration paramters of the reserve from a memory object
* @param self The reserve configuration * @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
**/ **/
function getParamsMemory(DataTypes.ReserveConfigurationMap memory self) function getParamsMemory(DataTypes.ReserveConfigurationMap memory self)
internal internal
@ -341,6 +419,22 @@ library ReserveConfiguration {
); );
} }
/**
* @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
);
}
/** /**
* @dev Gets the configuration flags of the reserve from a memory object * @dev Gets the configuration flags of the reserve from a memory object
* @param self The reserve configuration * @param self The reserve configuration
@ -363,4 +457,30 @@ library ReserveConfiguration {
(self.data & ~STABLE_BORROWING_MASK) != 0 (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;
}
} }

View File

@ -102,6 +102,10 @@ library Errors {
string public constant LP_NOT_CONTRACT = '78'; string public constant LP_NOT_CONTRACT = '78';
string public constant SDT_STABLE_DEBT_OVERFLOW = '79'; string public constant SDT_STABLE_DEBT_OVERFLOW = '79';
string public constant SDT_BURN_EXCEEDS_BALANCE = '80'; 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 { enum CollateralManagerErrors {
NO_ERROR, NO_ERROR,

View File

@ -14,6 +14,8 @@ import {UserConfiguration} from '../configuration/UserConfiguration.sol';
import {Errors} from '../helpers/Errors.sol'; import {Errors} from '../helpers/Errors.sol';
import {Helpers} from '../helpers/Helpers.sol'; import {Helpers} from '../helpers/Helpers.sol';
import {IReserveInterestRateStrategy} from '../../../interfaces/IReserveInterestRateStrategy.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'; import {DataTypes} from '../types/DataTypes.sol';
/** /**
@ -39,14 +41,22 @@ library ValidationLogic {
* @param amount The amount to be deposited * @param amount The amount to be deposited
*/ */
function validateDeposit(DataTypes.ReserveData storage reserve, uint256 amount) internal view { 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();
uint256 supplyCap = reserveConfiguration.getSupplyCapMemory();
require(amount != 0, Errors.VL_INVALID_AMOUNT); require(amount != 0, Errors.VL_INVALID_AMOUNT);
require(isActive, Errors.VL_NO_ACTIVE_RESERVE); require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
require(!isFrozen, Errors.VL_RESERVE_FROZEN); require(!isFrozen, Errors.VL_RESERVE_FROZEN);
require(
supplyCap == 0 ||
IERC20(reserve.aTokenAddress).totalSupply().add(amount).div(10**reserveDecimals) <
supplyCap,
Errors.VL_SUPPLY_CAP_EXCEEDED
);
} }
/** /**
* @dev Validates a withdraw action * @dev Validates a withdraw action
* @param reserve The reserve object * @param reserve The reserve object
@ -57,7 +67,7 @@ library ValidationLogic {
DataTypes.ReserveData storage reserve, DataTypes.ReserveData storage reserve,
uint256 amount, uint256 amount,
uint256 userBalance uint256 userBalance
) internal view { ) external view {
require(amount != 0, Errors.VL_INVALID_AMOUNT); require(amount != 0, Errors.VL_INVALID_AMOUNT);
require(amount <= userBalance, Errors.VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE); require(amount <= userBalance, Errors.VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE);
@ -73,6 +83,10 @@ library ValidationLogic {
uint256 userBorrowBalanceETH; uint256 userBorrowBalanceETH;
uint256 availableLiquidity; uint256 availableLiquidity;
uint256 healthFactor; uint256 healthFactor;
uint256 totalSupplyStableDebt;
uint256 totalSupplyVariableDebt;
uint256 reserveDecimals;
uint256 borrowCap;
bool isActive; bool isActive;
bool isFrozen; bool isFrozen;
bool borrowingEnabled; bool borrowingEnabled;
@ -110,9 +124,15 @@ library ValidationLogic {
) internal view { ) internal view {
ValidateBorrowLocalVars memory vars; ValidateBorrowLocalVars memory vars;
(vars.isActive, vars.isFrozen, vars.borrowingEnabled, vars.stableRateBorrowingEnabled) = reserve DataTypes.ReserveConfigurationMap memory reserveConfiguration = reserve.configuration;
.configuration (, , , vars.reserveDecimals, ) = reserveConfiguration.getParamsMemory();
.getFlags();
(
vars.isActive,
vars.isFrozen,
vars.borrowingEnabled,
vars.stableRateBorrowingEnabled
) = reserveConfiguration.getFlagsMemory();
require(vars.isActive, Errors.VL_NO_ACTIVE_RESERVE); require(vars.isActive, Errors.VL_NO_ACTIVE_RESERVE);
require(!vars.isFrozen, Errors.VL_RESERVE_FROZEN); require(!vars.isFrozen, Errors.VL_RESERVE_FROZEN);
@ -127,6 +147,19 @@ library ValidationLogic {
Errors.VL_INVALID_INTEREST_RATE_MODE_SELECTED Errors.VL_INVALID_INTEREST_RATE_MODE_SELECTED
); );
vars.totalSupplyStableDebt = IERC20(reserve.stableDebtTokenAddress).totalSupply();
vars.borrowCap = reserveConfiguration.getBorrowCapMemory();
vars.totalSupplyVariableDebt = IERC20(reserve.variableDebtTokenAddress).totalSupply();
require(
vars.borrowCap == 0 ||
vars.totalSupplyStableDebt.add(vars.totalSupplyVariableDebt).add(amount).div(
10**vars.reserveDecimals
) <
vars.borrowCap,
Errors.VL_BORROW_CAP_EXCEEDED
);
( (
vars.userCollateralBalanceETH, vars.userCollateralBalanceETH,
vars.userBorrowBalanceETH, vars.userBorrowBalanceETH,
@ -204,7 +237,7 @@ library ValidationLogic {
address onBehalfOf, address onBehalfOf,
uint256 stableDebt, uint256 stableDebt,
uint256 variableDebt uint256 variableDebt
) internal view { ) external view {
bool isActive = reserve.configuration.getActive(); bool isActive = reserve.configuration.getActive();
require(isActive, Errors.VL_NO_ACTIVE_RESERVE); require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
@ -313,9 +346,7 @@ library ValidationLogic {
* @dev Validates the action of setting an asset as collateral * @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 * @param reserve The state of the reserve that the user is enabling or disabling as collateral
*/ */
function validateSetUseReserveAsCollateral( function validateSetUseReserveAsCollateral(DataTypes.ReserveData storage reserve) external view {
DataTypes.ReserveData storage reserve
) external view {
uint256 underlyingBalance = IERC20(reserve.aTokenAddress).balanceOf(msg.sender); uint256 underlyingBalance = IERC20(reserve.aTokenAddress).balanceOf(msg.sender);
require(underlyingBalance > 0, Errors.VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0); require(underlyingBalance > 0, Errors.VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0);
@ -326,7 +357,7 @@ library ValidationLogic {
* @param assets The assets being flashborrowed * @param assets The assets being flashborrowed
* @param amounts The amounts for each asset being borrowed * @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); require(assets.length == amounts.length, Errors.VL_INCONSISTENT_FLASHLOAN_PARAMS);
} }

View File

@ -38,6 +38,8 @@ library DataTypes {
//bit 59: stable rate borrowing enabled //bit 59: stable rate borrowing enabled
//bit 60-63: reserved //bit 60-63: reserved
//bit 64-79: reserve factor //bit 64-79: reserve factor
//bit 80-115 borrow cap, borrowCap == 0 => disabled
//bit 116-152 supply cap, supplyCap == 0 => disabled
uint256 data; uint256 data;
} }

View File

@ -15,6 +15,8 @@ export const oneEther = new BigNumber(Math.pow(10, 18));
export const oneRay = new BigNumber(Math.pow(10, 27)); export const oneRay = new BigNumber(Math.pow(10, 27));
export const MAX_UINT_AMOUNT = export const MAX_UINT_AMOUNT =
'115792089237316195423570985008687907853269984665640564039457584007913129639935'; '115792089237316195423570985008687907853269984665640564039457584007913129639935';
export const MAX_BORROW_CAP = '68719476735';
export const MAX_SUPPLY_CAP = '68719476735';
export const ONE_YEAR = '31536000'; export const ONE_YEAR = '31536000';
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
export const ONE_ADDRESS = '0x0000000000000000000000000000000000000001'; export const ONE_ADDRESS = '0x0000000000000000000000000000000000000001';

View File

@ -284,6 +284,8 @@ export const configureReservesByHelper = async (
liquidationThreshold: BigNumberish; liquidationThreshold: BigNumberish;
liquidationBonus: BigNumberish; liquidationBonus: BigNumberish;
reserveFactor: BigNumberish; reserveFactor: BigNumberish;
borrowCap: BigNumberish;
supplyCap: BigNumberish;
stableBorrowingEnabled: boolean; stableBorrowingEnabled: boolean;
borrowingEnabled: boolean; borrowingEnabled: boolean;
}[] = []; }[] = [];
@ -295,6 +297,8 @@ export const configureReservesByHelper = async (
liquidationBonus, liquidationBonus,
liquidationThreshold, liquidationThreshold,
reserveFactor, reserveFactor,
borrowCap,
supplyCap,
stableBorrowRateEnabled, stableBorrowRateEnabled,
borrowingEnabled, borrowingEnabled,
}, },
@ -326,9 +330,11 @@ export const configureReservesByHelper = async (
inputParams.push({ inputParams.push({
asset: tokenAddress, asset: tokenAddress,
baseLTV: baseLTVAsCollateral, baseLTV: baseLTVAsCollateral,
liquidationThreshold: liquidationThreshold, liquidationThreshold,
liquidationBonus: liquidationBonus, liquidationBonus,
reserveFactor: reserveFactor, reserveFactor,
borrowCap,
supplyCap,
stableBorrowingEnabled: stableBorrowRateEnabled, stableBorrowingEnabled: stableBorrowRateEnabled,
borrowingEnabled: borrowingEnabled, borrowingEnabled: borrowingEnabled,
}); });

View File

@ -177,6 +177,10 @@ export enum ProtocolErrors {
RC_INVALID_DECIMALS = '70', RC_INVALID_DECIMALS = '70',
RC_INVALID_RESERVE_FACTOR = '71', RC_INVALID_RESERVE_FACTOR = '71',
LPAPR_INVALID_ADDRESSES_PROVIDER_ID = '72', 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 // old
@ -356,6 +360,7 @@ export enum TokenContractId {
export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams {
aTokenImpl: eContractid; aTokenImpl: eContractid;
reserveFactor: string; reserveFactor: string;
supplyCap: string;
strategy: IInterestRateStrategyParams; strategy: IInterestRateStrategyParams;
} }
@ -379,6 +384,7 @@ export interface IReserveBorrowParams {
borrowingEnabled: boolean; borrowingEnabled: boolean;
stableBorrowRateEnabled: boolean; stableBorrowRateEnabled: boolean;
reserveDecimals: string; reserveDecimals: string;
borrowCap: string;
} }
export interface IReserveCollateralParams { export interface IReserveCollateralParams {

View File

@ -1,6 +1,6 @@
import { eContractid, IReserveParams } from '../../helpers/types'; import { eContractid, IReserveParams } from '../../helpers/types';
import { import {
rateStrategyStableOne, rateStrategyStableOne,
rateStrategyStableTwo, rateStrategyStableTwo,
rateStrategyStableThree, rateStrategyStableThree,
@ -21,7 +21,9 @@ export const strategyBUSD: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyDAI: IReserveParams = { export const strategyDAI: IReserveParams = {
@ -33,7 +35,9 @@ export const strategyDAI: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategySUSD: IReserveParams = { export const strategySUSD: IReserveParams = {
@ -45,7 +49,9 @@ export const strategySUSD: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyTUSD: IReserveParams = { export const strategyTUSD: IReserveParams = {
@ -57,7 +63,9 @@ export const strategyTUSD: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyUSDC: IReserveParams = { export const strategyUSDC: IReserveParams = {
@ -69,7 +77,9 @@ export const strategyUSDC: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '6', reserveDecimals: '6',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyUSDT: IReserveParams = { export const strategyUSDT: IReserveParams = {
@ -81,7 +91,9 @@ export const strategyUSDT: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '6', reserveDecimals: '6',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyAAVE: IReserveParams = { export const strategyAAVE: IReserveParams = {
@ -93,7 +105,9 @@ export const strategyAAVE: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '0' reserveFactor: '0',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyBAT: IReserveParams = { export const strategyBAT: IReserveParams = {
@ -105,7 +119,9 @@ export const strategyBAT: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyENJ: IReserveParams = { export const strategyENJ: IReserveParams = {
@ -117,7 +133,9 @@ export const strategyENJ: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyWETH: IReserveParams = { export const strategyWETH: IReserveParams = {
@ -129,7 +147,9 @@ export const strategyWETH: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyKNC: IReserveParams = { export const strategyKNC: IReserveParams = {
@ -141,7 +161,9 @@ export const strategyKNC: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyLINK: IReserveParams = { export const strategyLINK: IReserveParams = {
@ -153,7 +175,9 @@ export const strategyLINK: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyMANA: IReserveParams = { export const strategyMANA: IReserveParams = {
@ -165,7 +189,9 @@ export const strategyMANA: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '3500' reserveFactor: '3500',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyMKR: IReserveParams = { export const strategyMKR: IReserveParams = {
@ -177,7 +203,9 @@ export const strategyMKR: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyREN: IReserveParams = { export const strategyREN: IReserveParams = {
@ -189,7 +217,9 @@ export const strategyREN: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategySNX: IReserveParams = { export const strategySNX: IReserveParams = {
@ -201,7 +231,9 @@ export const strategySNX: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '3500' reserveFactor: '3500',
borrowCap: '0',
supplyCap: '0',
}; };
// Invalid borrow rates in params currently, replaced with snx params // Invalid borrow rates in params currently, replaced with snx params
@ -214,7 +246,9 @@ export const strategyUNI: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.DelegationAwareAToken, aTokenImpl: eContractid.DelegationAwareAToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyWBTC: IReserveParams = { export const strategyWBTC: IReserveParams = {
@ -226,7 +260,9 @@ export const strategyWBTC: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '8', reserveDecimals: '8',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyYFI: IReserveParams = { export const strategyYFI: IReserveParams = {
@ -238,7 +274,9 @@ export const strategyYFI: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyZRX: IReserveParams = { export const strategyZRX: IReserveParams = {
@ -250,7 +288,9 @@ export const strategyZRX: IReserveParams = {
stableBorrowRateEnabled: true, stableBorrowRateEnabled: true,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyXSUSHI: IReserveParams = { export const strategyXSUSHI: IReserveParams = {
@ -263,4 +303,6 @@ export const strategyXSUSHI: IReserveParams = {
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '3500', reserveFactor: '3500',
}; borrowCap: '0',
supplyCap: '0',
};

View File

@ -1,10 +1,5 @@
import { eContractid, IReserveParams} from '../../helpers/types'; import { eContractid, IReserveParams } from '../../helpers/types';
import { import { rateStrategyAmmBase, rateStrategyStable, rateStrategyBaseOne } from './rateStrategies';
rateStrategyAmmBase,
rateStrategyStable,
rateStrategyBaseOne,
} from './rateStrategies';
export const strategyWETH: IReserveParams = { export const strategyWETH: IReserveParams = {
strategy: rateStrategyBaseOne, strategy: rateStrategyBaseOne,
@ -15,7 +10,9 @@ export const strategyWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyWBTC: IReserveParams = { export const strategyWBTC: IReserveParams = {
@ -27,7 +24,9 @@ export const strategyWBTC: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '8', reserveDecimals: '8',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyDAI: IReserveParams = { export const strategyDAI: IReserveParams = {
@ -39,7 +38,9 @@ export const strategyDAI: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyUSDC: IReserveParams = { export const strategyUSDC: IReserveParams = {
@ -51,7 +52,9 @@ export const strategyUSDC: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '6', reserveDecimals: '6',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyUSDT: IReserveParams = { export const strategyUSDT: IReserveParams = {
@ -63,7 +66,9 @@ export const strategyUSDT: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '6', reserveDecimals: '6',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyDAIWETH: IReserveParams = { export const strategyDAIWETH: IReserveParams = {
@ -75,7 +80,9 @@ export const strategyDAIWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyWBTCWETH: IReserveParams = { export const strategyWBTCWETH: IReserveParams = {
@ -87,7 +94,9 @@ export const strategyWBTCWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1500' reserveFactor: '1500',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyAAVEWETH: IReserveParams = { export const strategyAAVEWETH: IReserveParams = {
@ -99,7 +108,9 @@ export const strategyAAVEWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '500' reserveFactor: '500',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyBATWETH: IReserveParams = { export const strategyBATWETH: IReserveParams = {
@ -111,7 +122,9 @@ export const strategyBATWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1500' reserveFactor: '1500',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyDAIUSDC: IReserveParams = { export const strategyDAIUSDC: IReserveParams = {
@ -123,7 +136,9 @@ export const strategyDAIUSDC: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyCRVWETH: IReserveParams = { export const strategyCRVWETH: IReserveParams = {
@ -135,7 +150,9 @@ export const strategyCRVWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1500' reserveFactor: '1500',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyLINKWETH: IReserveParams = { export const strategyLINKWETH: IReserveParams = {
@ -147,7 +164,9 @@ export const strategyLINKWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1500' reserveFactor: '1500',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyMKRWETH: IReserveParams = { export const strategyMKRWETH: IReserveParams = {
@ -159,7 +178,9 @@ export const strategyMKRWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1500' reserveFactor: '1500',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyRENWETH: IReserveParams = { export const strategyRENWETH: IReserveParams = {
@ -171,7 +192,9 @@ export const strategyRENWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1500' reserveFactor: '1500',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategySNXWETH: IReserveParams = { export const strategySNXWETH: IReserveParams = {
@ -183,7 +206,9 @@ export const strategySNXWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000' reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyUNIWETH: IReserveParams = { export const strategyUNIWETH: IReserveParams = {
@ -195,7 +220,9 @@ export const strategyUNIWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1500' reserveFactor: '1500',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyUSDCWETH: IReserveParams = { export const strategyUSDCWETH: IReserveParams = {
@ -207,7 +234,9 @@ export const strategyUSDCWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000' reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyWBTCUSDC: IReserveParams = { export const strategyWBTCUSDC: IReserveParams = {
@ -219,7 +248,9 @@ export const strategyWBTCUSDC: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1500' reserveFactor: '1500',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyYFIWETH: IReserveParams = { export const strategyYFIWETH: IReserveParams = {
@ -231,7 +262,9 @@ export const strategyYFIWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1500' reserveFactor: '1500',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyBALWETH: IReserveParams = { export const strategyBALWETH: IReserveParams = {
@ -243,5 +276,7 @@ export const strategyBALWETH: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1500' reserveFactor: '1500',
} borrowCap: '0',
supplyCap: '0',
};

View File

@ -20,6 +20,8 @@ export const strategyDAI: IReserveParams = {
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000', reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyUSDC: IReserveParams = { export const strategyUSDC: IReserveParams = {
@ -32,6 +34,8 @@ export const strategyUSDC: IReserveParams = {
reserveDecimals: '6', reserveDecimals: '6',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000', reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyUSDT: IReserveParams = { export const strategyUSDT: IReserveParams = {
@ -44,6 +48,8 @@ export const strategyUSDT: IReserveParams = {
reserveDecimals: '6', reserveDecimals: '6',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000', reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyWETH: IReserveParams = { export const strategyWETH: IReserveParams = {
@ -56,6 +62,8 @@ export const strategyWETH: IReserveParams = {
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '1000', reserveFactor: '1000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyWBTC: IReserveParams = { export const strategyWBTC: IReserveParams = {
@ -68,6 +76,8 @@ export const strategyWBTC: IReserveParams = {
reserveDecimals: '8', reserveDecimals: '8',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
reserveFactor: '2000', reserveFactor: '2000',
borrowCap: '0',
supplyCap: '0',
}; };
export const strategyMATIC: IReserveParams = { export const strategyMATIC: IReserveParams = {
@ -79,6 +89,8 @@ export const strategyMATIC: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
borrowCap: '0',
supplyCap: '0',
reserveFactor: '2000', reserveFactor: '2000',
}; };
@ -91,5 +103,7 @@ export const strategyAAVE: IReserveParams = {
stableBorrowRateEnabled: false, stableBorrowRateEnabled: false,
reserveDecimals: '18', reserveDecimals: '18',
aTokenImpl: eContractid.AToken, aTokenImpl: eContractid.AToken,
borrowCap: '0',
supplyCap: '0',
reserveFactor: '0', reserveFactor: '0',
}; };

View File

@ -149,7 +149,8 @@
"Andrey Kozlov <andrey@aave.com>", "Andrey Kozlov <andrey@aave.com>",
"David Racero <david.k@aave.com>", "David Racero <david.k@aave.com>",
"Pol Sendra <pol@aave.com>", "Pol Sendra <pol@aave.com>",
"David Truong <david@aave.com>" "David Truong <david@aave.com>",
"Hadrien Charlanes <hadrien@aave.com>"
], ],
"license": "AGPLv3", "license": "AGPLv3",
"dependencies": { "dependencies": {

View File

@ -0,0 +1,354 @@
import { TestEnv, makeSuite } from './helpers/make-suite';
import {
APPROVAL_AMOUNT_LENDING_POOL,
MAX_UINT_AMOUNT,
RAY,
MAX_BORROW_CAP,
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('Borrow Cap', (testEnv: TestEnv) => {
const { VL_BORROW_CAP_EXCEEDED, RC_INVALID_BORROW_CAP } = ProtocolErrors;
const unitParse = async (token: WETH9Mocked | MintableERC20, nb: string) =>
BigNumber.from(nb).mul(BigNumber.from('10').pow((await token.decimals()) - 3));
it('Reserves should initially have borrow cap disabled (borrowCap = 0)', async () => {
const {
configurator,
weth,
pool,
dai,
usdc,
deployer,
helpersContract,
users: [user1],
} = testEnv;
const mintedAmount = parseEther('1000000000');
// minting for main user
await dai.mint(mintedAmount);
await weth.mint(mintedAmount);
await usdc.mint(mintedAmount);
// minting for lp user
await dai.connect(user1.signer).mint(mintedAmount);
await weth.connect(user1.signer).mint(mintedAmount);
await usdc.connect(user1.signer).mint(mintedAmount);
await dai.approve(pool.address, MAX_UINT_AMOUNT);
await weth.approve(pool.address, MAX_UINT_AMOUNT);
await usdc.approve(pool.address, MAX_UINT_AMOUNT);
await dai.connect(user1.signer).approve(pool.address, MAX_UINT_AMOUNT);
await weth.connect(user1.signer).approve(pool.address, MAX_UINT_AMOUNT);
await usdc.connect(user1.signer).approve(pool.address, MAX_UINT_AMOUNT);
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');
});
it('Should be able to borrow 10 Dai stable, 10 USDC variable', async () => {
const {
configurator,
weth,
pool,
dai,
usdc,
deployer,
helpersContract,
users: [user1],
} = testEnv;
const suppliedAmount = 1000;
const precisionSuppliedAmount = (suppliedAmount * 1000).toString();
const borrowedAmount = 10;
const precisionBorrowedAmount = (borrowedAmount * 1000).toString();
// deposit collateral
await pool.deposit(
weth.address,
await unitParse(weth, precisionSuppliedAmount),
deployer.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 precisionBorrowedAmount = (borrowedAmount * 1000).toString();
await expect(
pool.borrow(
usdc.address,
await unitParse(usdc, precisionBorrowedAmount),
2,
0,
deployer.address
)
).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED);
await expect(
pool.borrow(
dai.address,
await unitParse(dai, precisionBorrowedAmount),
2,
0,
deployer.address
)
).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;
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
);
});
it('Sets the borrow cap for usdc and DAI to 120 Units', async () => {
const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv;
const newCap = '120';
await configurator.setBorrowCap(usdc.address, newCap);
await configurator.setBorrowCap(dai.address, newCap);
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);
});
it('Should succeed to borrow 10 stable dai and 10 variable usdc', async () => {
const { usdc, pool, dai, deployer, helpersContract } = testEnv;
const borrowedAmount = 10;
const precisionBorrowedAmount = (borrowedAmount * 1000).toString();
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('should fail to borrow 100 variable dai and 100 stable usdc', async () => {
const { usdc, pool, dai, deployer, helpersContract } = testEnv;
const borrowedAmount = 100;
const precisionBorrowedAmount = (borrowedAmount * 1000).toString();
await expect(
pool.borrow(
usdc.address,
await unitParse(usdc, precisionBorrowedAmount),
1,
0,
deployer.address
)
).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED);
await expect(
pool.borrow(
dai.address,
await unitParse(dai, precisionBorrowedAmount),
2,
0,
deployer.address
)
).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 precisionBorrowedAmount = (borrowedAmount * 1000).toString();
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('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.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.getReserveCaps(usdc.address)).borrowCap;
daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap;
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 precisionBorrowedAmount = (borrowedAmount * 1000).toString();
await pool.borrow(
usdc.address,
await unitParse(usdc, precisionBorrowedAmount),
1,
0,
deployer.address
);
await pool.borrow(
dai.address,
await unitParse(dai, precisionBorrowedAmount),
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.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.getReserveCaps(usdc.address)).borrowCap;
daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap;
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 precisionBorrowedAmount = (borrowedAmount * 1000).toString();
await expect(
pool.borrow(
usdc.address,
await unitParse(usdc, precisionBorrowedAmount),
1,
0,
deployer.address
)
).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED);
await expect(
pool.borrow(
dai.address,
await unitParse(dai, precisionBorrowedAmount),
2,
0,
deployer.address
)
).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.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.getReserveCaps(usdc.address)).borrowCap;
daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap;
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 precisionBorrowedAmount = (borrowedAmount * 1000).toString();
await pool.borrow(
usdc.address,
await unitParse(usdc, precisionBorrowedAmount),
1,
0,
deployer.address
);
await pool.borrow(
dai.address,
await unitParse(dai, precisionBorrowedAmount),
2,
0,
deployer.address
);
});
});

View File

@ -1,8 +1,14 @@
import { TestEnv, makeSuite } from './helpers/make-suite'; 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 { convertToCurrencyDecimals } from '../../helpers/contracts-helpers';
import { ProtocolErrors } from '../../helpers/types'; import { ProtocolErrors } from '../../helpers/types';
import { strategyWETH } from '../../markets/aave/reservesConfigs'; import { strategyWETH } from '../../markets/aave/reservesConfigs';
import { BigNumber } from '@ethersproject/bignumber';
const { expect } = require('chai'); const { expect } = require('chai');
@ -15,6 +21,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
RC_INVALID_LIQ_BONUS, RC_INVALID_LIQ_BONUS,
RC_INVALID_DECIMALS, RC_INVALID_DECIMALS,
RC_INVALID_RESERVE_FACTOR, RC_INVALID_RESERVE_FACTOR,
RC_INVALID_BORROW_CAP,
RC_INVALID_SUPPLY_CAP,
} = ProtocolErrors; } = ProtocolErrors;
it('Reverts trying to set an invalid reserve factor', async () => { it('Reverts trying to set an invalid reserve factor', async () => {
@ -73,6 +81,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
isActive, isActive,
isFrozen, isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address); } = await helpersContract.getReserveConfigurationData(weth.address);
const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address);
expect(borrowingEnabled).to.be.equal(true); expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true); expect(isActive).to.be.equal(true);
@ -83,6 +92,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); 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 () => { it('Unfreezes the ETH reserve', async () => {
@ -100,6 +111,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
isActive, isActive,
isFrozen, isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address); } = await helpersContract.getReserveConfigurationData(weth.address);
const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address);
expect(borrowingEnabled).to.be.equal(true); expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true); expect(isActive).to.be.equal(true);
@ -110,6 +122,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); 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 () => { it('Check the onlyAaveAdmin on freezeReserve ', async () => {
@ -142,6 +156,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
isActive, isActive,
isFrozen, isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address); } = await helpersContract.getReserveConfigurationData(weth.address);
const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address);
expect(borrowingEnabled).to.be.equal(false); expect(borrowingEnabled).to.be.equal(false);
expect(isActive).to.be.equal(true); expect(isActive).to.be.equal(true);
@ -152,11 +167,13 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); 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 () => { it('Activates the ETH reserve for borrowing', async () => {
const { configurator, weth, helpersContract } = testEnv; const { configurator, weth, helpersContract } = testEnv;
await configurator.enableBorrowingOnReserve(weth.address, true); await configurator.enableBorrowingOnReserve(weth.address, '0', true);
const { variableBorrowIndex } = await helpersContract.getReserveData(weth.address); const { variableBorrowIndex } = await helpersContract.getReserveData(weth.address);
const { const {
@ -170,6 +187,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
isActive, isActive,
isFrozen, isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address); } = await helpersContract.getReserveConfigurationData(weth.address);
const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address);
expect(borrowingEnabled).to.be.equal(true); expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true); expect(isActive).to.be.equal(true);
@ -180,6 +198,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); 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); expect(variableBorrowIndex.toString()).to.be.equal(RAY);
}); });
@ -195,7 +215,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => { it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => {
const { configurator, users, weth } = testEnv; const { configurator, users, weth } = testEnv;
await expect( await expect(
configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, true), configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, '0', true),
CALLER_NOT_POOL_ADMIN CALLER_NOT_POOL_ADMIN
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
}); });
@ -215,6 +235,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
isActive, isActive,
isFrozen, isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address); } = await helpersContract.getReserveConfigurationData(weth.address);
const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address);
expect(borrowingEnabled).to.be.equal(true); expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true); expect(isActive).to.be.equal(true);
@ -225,6 +246,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(liquidationBonus).to.be.equal(0); expect(liquidationBonus).to.be.equal(0);
expect(stableBorrowRateEnabled).to.be.equal(true); expect(stableBorrowRateEnabled).to.be.equal(true);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); 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 () => { it('Activates the ETH reserve as collateral', async () => {
@ -242,6 +265,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
isActive, isActive,
isFrozen, isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address); } = await helpersContract.getReserveConfigurationData(weth.address);
const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address);
expect(borrowingEnabled).to.be.equal(true); expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true); expect(isActive).to.be.equal(true);
@ -252,6 +276,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); 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 () => { it('Check the onlyAaveAdmin on configureReserveAsCollateral ', async () => {
@ -278,6 +304,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
isActive, isActive,
isFrozen, isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address); } = await helpersContract.getReserveConfigurationData(weth.address);
const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address);
expect(borrowingEnabled).to.be.equal(true); expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true); expect(isActive).to.be.equal(true);
@ -288,6 +315,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(false); expect(stableBorrowRateEnabled).to.be.equal(false);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); 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 () => { it('Enables stable borrow rate on the ETH reserve', async () => {
@ -304,6 +333,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
isActive, isActive,
isFrozen, isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address); } = await helpersContract.getReserveConfigurationData(weth.address);
const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address);
expect(borrowingEnabled).to.be.equal(true); expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true); expect(isActive).to.be.equal(true);
@ -314,6 +344,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(true); expect(stableBorrowRateEnabled).to.be.equal(true);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); 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 () => { it('Check the onlyAaveAdmin on disableReserveStableRate', async () => {
@ -332,6 +364,29 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); ).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('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 () => { it('Changes the reserve factor of WETH', async () => {
const { configurator, helpersContract, weth } = testEnv; const { configurator, helpersContract, weth } = testEnv;
await configurator.setReserveFactor(weth.address, '1000'); await configurator.setReserveFactor(weth.address, '1000');
@ -346,6 +401,51 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
isActive, isActive,
isFrozen, isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address); } = 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(borrowCap).to.be.equal(strategyWETH.borrowCap);
expect(supplyCap).to.be.equal(strategyWETH.supplyCap);
expect(reserveFactor).to.be.equal(1000);
});
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('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)),
CALLER_NOT_POOL_ADMIN
).to.be.revertedWith(RC_INVALID_SUPPLY_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, supplyCap } = await helpersContract.getReserveCaps(weth.address);
expect(borrowingEnabled).to.be.equal(true); expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true); expect(isActive).to.be.equal(true);
@ -356,14 +456,37 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled);
expect(reserveFactor).to.be.equal(1000); expect(reserveFactor).to.be.equal(1000);
expect(borrowCap).to.be.equal('3000000');
expect(supplyCap).to.be.equal(strategyWETH.supplyCap);
}); });
it('Check the onlyLendingPoolManager on setReserveFactor', async () => { it('Changes the supply Cap of WETH', async () => {
const { configurator, users, weth } = testEnv; const { configurator, helpersContract, weth } = testEnv;
await expect( await configurator.setSupplyCap(weth.address, '3000000');
configurator.connect(users[2].signer).setReserveFactor(weth.address, '2000'), const {
CALLER_NOT_POOL_ADMIN decimals,
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); 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 () => { it('Reverts when trying to disable the DAI reserve with liquidity on it', async () => {

View File

@ -0,0 +1,299 @@
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 unitParse = async (token: WETH9Mocked | MintableERC20, nb: string) =>
BigNumber.from(nb).mul(BigNumber.from('10').pow((await token.decimals()) - 3));
it('Reserves should initially have supply cap disabled (supplyCap = 0)', 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('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;
const suppliedAmount = 1000;
const precisionSuppliedAmount = (suppliedAmount * 1000).toString();
await pool.deposit(
usdc.address,
await unitParse(usdc, precisionSuppliedAmount),
deployer.address,
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 precisionSuppliedAmount = (suppliedAmount * 1000).toString();
await expect(
pool.deposit(
usdc.address,
await unitParse(usdc, precisionSuppliedAmount),
deployer.address,
0
)
).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED);
await expect(
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;
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 1110 Units', async () => {
const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv;
const newCap = '1110';
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 succeed to supply 10 dai and 10 usdc', async () => {
const { usdc, pool, dai, deployer, helpersContract } = testEnv;
const suppliedAmount = 10;
const precisionSuppliedAmount = (suppliedAmount * 1000).toString();
await pool.deposit(
usdc.address,
await unitParse(usdc, precisionSuppliedAmount),
deployer.address,
0
);
await pool.deposit(
dai.address,
await unitParse(dai, precisionSuppliedAmount),
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 precisionSuppliedAmount = (suppliedAmount * 1000).toString();
await expect(
pool.deposit(
usdc.address,
await unitParse(usdc, precisionSuppliedAmount),
deployer.address,
0
)
).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED);
await expect(
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 precisionSuppliedAmount = (suppliedAmount * 1000).toString();
await pool.deposit(
usdc.address,
await unitParse(usdc, precisionSuppliedAmount),
deployer.address,
0
);
await pool.deposit(
dai.address,
await unitParse(dai, precisionSuppliedAmount),
deployer.address,
0
);
});
it('Raises the supply cap for usdc and DAI to 2000 Units', async () => {
const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv;
const newCap = '2000';
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 succeed to supply 100 dai and 100 usdc', async () => {
const { usdc, pool, dai, deployer, helpersContract } = testEnv;
const suppliedAmount = 100;
const precisionSuppliedAmount = (suppliedAmount * 1000).toString();
await pool.deposit(
usdc.address,
await unitParse(usdc, precisionSuppliedAmount),
deployer.address,
0
);
await pool.deposit(
dai.address,
await unitParse(dai, precisionSuppliedAmount),
deployer.address,
0
);
});
it('Lowers the supply cap for usdc and DAI to 1200 Units', async () => {
const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv;
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;
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 precisionSuppliedAmount = (suppliedAmount * 1000).toString();
await expect(
pool.deposit(
usdc.address,
await unitParse(usdc, precisionSuppliedAmount),
deployer.address,
0
)
).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED);
await expect(
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;
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 precisionSuppliedAmount = (suppliedAmount * 1000).toString();
await pool.deposit(
usdc.address,
await unitParse(usdc, precisionSuppliedAmount),
deployer.address,
0
);
await pool.deposit(
dai.address,
await unitParse(dai, precisionSuppliedAmount),
deployer.address,
0
);
});
});

View File

@ -1,5 +1,5 @@
import { TestEnv, makeSuite } from './helpers/make-suite'; 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 { convertToCurrencyDecimals } from '../../helpers/contracts-helpers';
import { ProtocolErrors } from '../../helpers/types'; import { ProtocolErrors } from '../../helpers/types';
import { strategyWETH } from '../../markets/amm/reservesConfigs'; import { strategyWETH } from '../../markets/amm/reservesConfigs';
@ -156,7 +156,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
it('Activates the ETH reserve for borrowing', async () => { it('Activates the ETH reserve for borrowing', async () => {
const { configurator, weth, helpersContract } = testEnv; 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 { variableBorrowIndex } = await helpersContract.getReserveData(weth.address);
const { const {
@ -178,9 +178,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral);
expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold);
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); 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(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
expect(variableBorrowIndex.toString()).to.be.equal(RAY); expect(variableBorrowIndex.toString()).to.be.equal(RAY);
}); });
@ -195,7 +194,9 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => { it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => {
const { configurator, users, weth } = testEnv; const { configurator, users, weth } = testEnv;
await expect( 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 CALLER_NOT_POOL_ADMIN
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
}); });
@ -250,7 +251,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral);
expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold);
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); 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(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
}); });