2020-05-29 16:45:37 +00:00
|
|
|
// SPDX-License-Identifier: agpl-3.0
|
2020-11-20 10:45:20 +00:00
|
|
|
pragma solidity 0.6.12;
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-11-23 10:28:57 +00:00
|
|
|
import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol';
|
|
|
|
import {IReserveInterestRateStrategy} from '../../interfaces/IReserveInterestRateStrategy.sol';
|
2020-08-20 07:51:21 +00:00
|
|
|
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
|
2020-09-10 11:21:50 +00:00
|
|
|
import {PercentageMath} from '../libraries/math/PercentageMath.sol';
|
2020-11-23 14:56:55 +00:00
|
|
|
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
|
2020-11-23 10:28:57 +00:00
|
|
|
import {ILendingRateOracle} from '../../interfaces/ILendingRateOracle.sol';
|
2021-03-01 14:58:31 +00:00
|
|
|
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
|
2020-05-29 16:45:37 +00:00
|
|
|
|
|
|
|
/**
|
2020-06-20 23:40:03 +00:00
|
|
|
* @title DefaultReserveInterestRateStrategy contract
|
2020-11-19 13:48:15 +00:00
|
|
|
* @notice Implements the calculation of the interest rates depending on the reserve state
|
|
|
|
* @dev The model of interest rate is based on 2 slopes, one before the `OPTIMAL_UTILIZATION_RATE`
|
|
|
|
* point of utilization and another from that one to 100%
|
|
|
|
* - An instance of this same contract, can't be used across different Aave markets, due to the caching
|
|
|
|
* of the LendingPoolAddressesProvider
|
2020-06-20 23:40:03 +00:00
|
|
|
* @author Aave
|
|
|
|
**/
|
2020-05-29 16:45:37 +00:00
|
|
|
contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
|
2020-06-20 23:40:03 +00:00
|
|
|
using WadRayMath for uint256;
|
|
|
|
using SafeMath for uint256;
|
2020-09-10 11:21:50 +00:00
|
|
|
using PercentageMath for uint256;
|
2020-11-19 13:48:15 +00:00
|
|
|
|
2020-06-20 23:40:03 +00:00
|
|
|
/**
|
2020-11-19 13:48:15 +00:00
|
|
|
* @dev this constant represents the utilization rate at which the pool aims to obtain most competitive borrow rates.
|
|
|
|
* Expressed in ray
|
2020-06-20 23:40:03 +00:00
|
|
|
**/
|
2020-11-19 16:17:11 +00:00
|
|
|
uint256 public immutable OPTIMAL_UTILIZATION_RATE;
|
2020-06-20 23:40:03 +00:00
|
|
|
|
|
|
|
/**
|
2020-11-19 13:48:15 +00:00
|
|
|
* @dev This constant represents the excess utilization rate above the optimal. It's always equal to
|
|
|
|
* 1-optimal utilization rate. Added as a constant here for gas optimizations.
|
|
|
|
* Expressed in ray
|
2020-06-20 23:40:03 +00:00
|
|
|
**/
|
|
|
|
|
2020-11-19 16:17:11 +00:00
|
|
|
uint256 public immutable EXCESS_UTILIZATION_RATE;
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-11-19 13:48:15 +00:00
|
|
|
ILendingPoolAddressesProvider public immutable addressesProvider;
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-11-19 13:48:15 +00:00
|
|
|
// Base variable borrow rate when Utilization rate = 0. Expressed in ray
|
2020-08-21 09:21:50 +00:00
|
|
|
uint256 internal immutable _baseVariableBorrowRate;
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-11-19 13:48:15 +00:00
|
|
|
// Slope of the variable interest curve when utilization rate > 0 and <= OPTIMAL_UTILIZATION_RATE. Expressed in ray
|
2020-08-21 09:21:50 +00:00
|
|
|
uint256 internal immutable _variableRateSlope1;
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-11-19 13:48:15 +00:00
|
|
|
// Slope of the variable interest curve when utilization rate > OPTIMAL_UTILIZATION_RATE. Expressed in ray
|
2020-08-21 09:21:50 +00:00
|
|
|
uint256 internal immutable _variableRateSlope2;
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-11-19 13:48:15 +00:00
|
|
|
// Slope of the stable interest curve when utilization rate > 0 and <= OPTIMAL_UTILIZATION_RATE. Expressed in ray
|
2020-08-21 09:21:50 +00:00
|
|
|
uint256 internal immutable _stableRateSlope1;
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-11-19 13:48:15 +00:00
|
|
|
// Slope of the stable interest curve when utilization rate > OPTIMAL_UTILIZATION_RATE. Expressed in ray
|
2020-08-21 09:21:50 +00:00
|
|
|
uint256 internal immutable _stableRateSlope2;
|
2020-06-20 23:40:03 +00:00
|
|
|
|
|
|
|
constructor(
|
2020-11-19 13:48:15 +00:00
|
|
|
ILendingPoolAddressesProvider provider,
|
2020-11-19 16:17:11 +00:00
|
|
|
uint256 optimalUtilizationRate,
|
2020-08-21 09:21:50 +00:00
|
|
|
uint256 baseVariableBorrowRate,
|
|
|
|
uint256 variableRateSlope1,
|
|
|
|
uint256 variableRateSlope2,
|
|
|
|
uint256 stableRateSlope1,
|
|
|
|
uint256 stableRateSlope2
|
2020-06-20 23:40:03 +00:00
|
|
|
) public {
|
2020-11-19 16:17:11 +00:00
|
|
|
OPTIMAL_UTILIZATION_RATE = optimalUtilizationRate;
|
|
|
|
EXCESS_UTILIZATION_RATE = WadRayMath.ray().sub(optimalUtilizationRate);
|
2020-08-21 09:21:50 +00:00
|
|
|
addressesProvider = provider;
|
|
|
|
_baseVariableBorrowRate = baseVariableBorrowRate;
|
|
|
|
_variableRateSlope1 = variableRateSlope1;
|
|
|
|
_variableRateSlope2 = variableRateSlope2;
|
|
|
|
_stableRateSlope1 = stableRateSlope1;
|
|
|
|
_stableRateSlope2 = stableRateSlope2;
|
2020-06-20 23:40:03 +00:00
|
|
|
}
|
|
|
|
|
2020-08-24 12:35:59 +00:00
|
|
|
function variableRateSlope1() external view returns (uint256) {
|
2020-08-21 09:21:50 +00:00
|
|
|
return _variableRateSlope1;
|
2020-06-20 23:40:03 +00:00
|
|
|
}
|
|
|
|
|
2020-08-24 12:35:59 +00:00
|
|
|
function variableRateSlope2() external view returns (uint256) {
|
2020-08-21 09:21:50 +00:00
|
|
|
return _variableRateSlope2;
|
2020-06-20 23:40:03 +00:00
|
|
|
}
|
|
|
|
|
2020-08-24 12:35:59 +00:00
|
|
|
function stableRateSlope1() external view returns (uint256) {
|
2020-08-21 09:21:50 +00:00
|
|
|
return _stableRateSlope1;
|
2020-06-20 23:40:03 +00:00
|
|
|
}
|
|
|
|
|
2020-08-24 12:35:59 +00:00
|
|
|
function stableRateSlope2() external view returns (uint256) {
|
2020-08-21 09:21:50 +00:00
|
|
|
return _stableRateSlope2;
|
2020-06-20 23:40:03 +00:00
|
|
|
}
|
|
|
|
|
2020-11-23 10:28:57 +00:00
|
|
|
function baseVariableBorrowRate() external view override returns (uint256) {
|
2020-08-21 09:21:50 +00:00
|
|
|
return _baseVariableBorrowRate;
|
2020-06-20 23:40:03 +00:00
|
|
|
}
|
|
|
|
|
2020-11-23 10:28:57 +00:00
|
|
|
function getMaxVariableBorrowRate() external view override returns (uint256) {
|
2020-09-21 17:52:22 +00:00
|
|
|
return _baseVariableBorrowRate.add(_variableRateSlope1).add(_variableRateSlope2);
|
|
|
|
}
|
2020-09-10 10:51:52 +00:00
|
|
|
|
2021-03-05 09:36:55 +00:00
|
|
|
/**
|
|
|
|
* @dev Calculates the interest rates depending on the reserve's state and configurations
|
|
|
|
* @param reserve The address of the reserve
|
|
|
|
* @param liquidityAdded The liquidity added during the operation
|
|
|
|
* @param liquidityTaken The liquidity taken during the operation
|
|
|
|
* @param totalStableDebt The total borrowed from the reserve a stable rate
|
|
|
|
* @param totalVariableDebt The total borrowed from the reserve at a variable rate
|
|
|
|
* @param averageStableBorrowRate The weighted average of all the stable rate loans
|
|
|
|
* @param reserveFactor The reserve portion of the interest that goes to the treasury of the market
|
|
|
|
* @return The liquidity rate, the stable borrow rate and the variable borrow rate
|
|
|
|
**/
|
|
|
|
function calculateInterestRates(
|
|
|
|
address reserve,
|
|
|
|
address aToken,
|
|
|
|
uint256 liquidityAdded,
|
|
|
|
uint256 liquidityTaken,
|
|
|
|
uint256 totalStableDebt,
|
|
|
|
uint256 totalVariableDebt,
|
|
|
|
uint256 averageStableBorrowRate,
|
|
|
|
uint256 reserveFactor
|
|
|
|
)
|
|
|
|
external
|
|
|
|
view
|
|
|
|
override
|
|
|
|
returns (
|
|
|
|
uint256,
|
|
|
|
uint256,
|
|
|
|
uint256
|
|
|
|
)
|
|
|
|
{
|
|
|
|
uint256 availableLiquidity = IERC20(reserve).balanceOf(aToken);
|
|
|
|
//avoid stack too deep
|
|
|
|
availableLiquidity = availableLiquidity.add(liquidityAdded).sub(liquidityTaken);
|
|
|
|
|
|
|
|
return
|
|
|
|
calculateInterestRates(
|
|
|
|
reserve,
|
|
|
|
availableLiquidity,
|
|
|
|
totalStableDebt,
|
|
|
|
totalVariableDebt,
|
|
|
|
averageStableBorrowRate,
|
|
|
|
reserveFactor
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-10-08 13:41:48 +00:00
|
|
|
struct CalcInterestRatesLocalVars {
|
2020-11-23 17:52:52 +00:00
|
|
|
uint256 totalDebt;
|
2020-09-10 10:51:52 +00:00
|
|
|
uint256 currentVariableBorrowRate;
|
|
|
|
uint256 currentStableBorrowRate;
|
|
|
|
uint256 currentLiquidityRate;
|
|
|
|
uint256 utilizationRate;
|
|
|
|
}
|
2020-09-21 17:52:22 +00:00
|
|
|
|
2020-06-20 23:40:03 +00:00
|
|
|
/**
|
2021-03-05 09:36:55 +00:00
|
|
|
* @dev Calculates the interest rates depending on the reserve's state and configurations.
|
|
|
|
* NOTE This function is kept for compatibility with the previous DefaultInterestRateStrategy interface.
|
|
|
|
* New protocol implementation uses the new calculateInterestRates() interface
|
2020-11-19 13:48:15 +00:00
|
|
|
* @param reserve The address of the reserve
|
2021-03-05 09:36:55 +00:00
|
|
|
* @param availableLiquidity The liquidity available in the corresponding aToken
|
2020-11-19 13:48:15 +00:00
|
|
|
* @param totalStableDebt The total borrowed from the reserve a stable rate
|
|
|
|
* @param totalVariableDebt The total borrowed from the reserve at a variable rate
|
|
|
|
* @param averageStableBorrowRate The weighted average of all the stable rate loans
|
|
|
|
* @param reserveFactor The reserve portion of the interest that goes to the treasury of the market
|
|
|
|
* @return The liquidity rate, the stable borrow rate and the variable borrow rate
|
2020-06-20 23:40:03 +00:00
|
|
|
**/
|
|
|
|
function calculateInterestRates(
|
2020-08-21 09:21:50 +00:00
|
|
|
address reserve,
|
2021-03-05 09:36:55 +00:00
|
|
|
uint256 availableLiquidity,
|
2020-09-14 13:13:30 +00:00
|
|
|
uint256 totalStableDebt,
|
|
|
|
uint256 totalVariableDebt,
|
2020-09-10 10:51:52 +00:00
|
|
|
uint256 averageStableBorrowRate,
|
|
|
|
uint256 reserveFactor
|
2020-06-20 23:40:03 +00:00
|
|
|
)
|
2021-03-05 09:36:55 +00:00
|
|
|
public
|
2020-06-20 23:40:03 +00:00
|
|
|
view
|
2020-11-23 10:28:57 +00:00
|
|
|
override
|
2020-06-20 23:40:03 +00:00
|
|
|
returns (
|
2020-08-21 09:21:50 +00:00
|
|
|
uint256,
|
|
|
|
uint256,
|
|
|
|
uint256
|
2020-05-29 16:45:37 +00:00
|
|
|
)
|
2020-06-20 23:40:03 +00:00
|
|
|
{
|
2020-09-10 10:51:52 +00:00
|
|
|
CalcInterestRatesLocalVars memory vars;
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-11-23 17:52:52 +00:00
|
|
|
vars.totalDebt = totalStableDebt.add(totalVariableDebt);
|
2020-09-10 10:51:52 +00:00
|
|
|
vars.currentVariableBorrowRate = 0;
|
|
|
|
vars.currentStableBorrowRate = 0;
|
|
|
|
vars.currentLiquidityRate = 0;
|
|
|
|
|
2021-03-05 09:36:55 +00:00
|
|
|
vars.utilizationRate = vars.totalDebt == 0
|
|
|
|
? 0
|
|
|
|
: vars.totalDebt.rayDiv(availableLiquidity.add(vars.totalDebt));
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-09-10 10:51:52 +00:00
|
|
|
vars.currentStableBorrowRate = ILendingRateOracle(addressesProvider.getLendingRateOracle())
|
2020-08-21 09:21:50 +00:00
|
|
|
.getMarketBorrowRate(reserve);
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2021-03-01 19:26:08 +00:00
|
|
|
if (vars.utilizationRate > OPTIMAL_UTILIZATION_RATE) {
|
2020-11-23 10:28:57 +00:00
|
|
|
uint256 excessUtilizationRateRatio =
|
2021-03-01 19:26:08 +00:00
|
|
|
vars.utilizationRate.sub(OPTIMAL_UTILIZATION_RATE).rayDiv(EXCESS_UTILIZATION_RATE);
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-09-10 10:51:52 +00:00
|
|
|
vars.currentStableBorrowRate = vars.currentStableBorrowRate.add(_stableRateSlope1).add(
|
2020-08-21 09:21:50 +00:00
|
|
|
_stableRateSlope2.rayMul(excessUtilizationRateRatio)
|
2020-06-20 23:40:03 +00:00
|
|
|
);
|
|
|
|
|
2020-09-10 10:51:52 +00:00
|
|
|
vars.currentVariableBorrowRate = _baseVariableBorrowRate.add(_variableRateSlope1).add(
|
2020-08-21 09:21:50 +00:00
|
|
|
_variableRateSlope2.rayMul(excessUtilizationRateRatio)
|
2020-06-20 23:40:03 +00:00
|
|
|
);
|
|
|
|
} else {
|
2020-09-10 10:51:52 +00:00
|
|
|
vars.currentStableBorrowRate = vars.currentStableBorrowRate.add(
|
2021-03-01 19:26:08 +00:00
|
|
|
_stableRateSlope1.rayMul(vars.utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE))
|
2020-06-20 23:40:03 +00:00
|
|
|
);
|
2020-09-10 10:51:52 +00:00
|
|
|
vars.currentVariableBorrowRate = _baseVariableBorrowRate.add(
|
2021-03-01 19:26:08 +00:00
|
|
|
vars.utilizationRate.rayMul(_variableRateSlope1).rayDiv(OPTIMAL_UTILIZATION_RATE)
|
2020-06-20 23:40:03 +00:00
|
|
|
);
|
2020-05-29 16:45:37 +00:00
|
|
|
}
|
|
|
|
|
2020-09-10 10:51:52 +00:00
|
|
|
vars.currentLiquidityRate = _getOverallBorrowRate(
|
2020-09-14 13:13:30 +00:00
|
|
|
totalStableDebt,
|
|
|
|
totalVariableDebt,
|
2020-10-08 13:41:48 +00:00
|
|
|
vars
|
|
|
|
.currentVariableBorrowRate,
|
2020-08-21 09:21:50 +00:00
|
|
|
averageStableBorrowRate
|
2020-06-20 23:40:03 +00:00
|
|
|
)
|
2021-03-01 19:26:08 +00:00
|
|
|
.rayMul(vars.utilizationRate)
|
2020-09-10 11:21:50 +00:00
|
|
|
.percentMul(PercentageMath.PERCENTAGE_FACTOR.sub(reserveFactor));
|
2020-08-21 09:21:50 +00:00
|
|
|
|
2020-10-08 13:41:48 +00:00
|
|
|
return (
|
|
|
|
vars.currentLiquidityRate,
|
|
|
|
vars.currentStableBorrowRate,
|
|
|
|
vars.currentVariableBorrowRate
|
|
|
|
);
|
2020-06-20 23:40:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-11-23 17:52:52 +00:00
|
|
|
* @dev Calculates the overall borrow rate as the weighted average between the total variable debt and total stable debt
|
2020-11-19 13:48:15 +00:00
|
|
|
* @param totalStableDebt The total borrowed from the reserve a stable rate
|
|
|
|
* @param totalVariableDebt The total borrowed from the reserve at a variable rate
|
|
|
|
* @param currentVariableBorrowRate The current variable borrow rate of the reserve
|
|
|
|
* @param currentAverageStableBorrowRate The current weighted average of all the stable rate loans
|
|
|
|
* @return The weighted averaged borrow rate
|
2020-06-20 23:40:03 +00:00
|
|
|
**/
|
2020-08-21 16:18:12 +00:00
|
|
|
function _getOverallBorrowRate(
|
2020-09-14 13:13:30 +00:00
|
|
|
uint256 totalStableDebt,
|
|
|
|
uint256 totalVariableDebt,
|
2020-08-21 09:21:50 +00:00
|
|
|
uint256 currentVariableBorrowRate,
|
|
|
|
uint256 currentAverageStableBorrowRate
|
2020-06-20 23:40:03 +00:00
|
|
|
) internal pure returns (uint256) {
|
2020-11-23 17:52:52 +00:00
|
|
|
uint256 totalDebt = totalStableDebt.add(totalVariableDebt);
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-11-23 17:52:52 +00:00
|
|
|
if (totalDebt == 0) return 0;
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-10-08 13:41:48 +00:00
|
|
|
uint256 weightedVariableRate = totalVariableDebt.wadToRay().rayMul(currentVariableBorrowRate);
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-10-08 13:41:48 +00:00
|
|
|
uint256 weightedStableRate = totalStableDebt.wadToRay().rayMul(currentAverageStableBorrowRate);
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-11-23 10:28:57 +00:00
|
|
|
uint256 overallBorrowRate =
|
2020-11-23 17:52:52 +00:00
|
|
|
weightedVariableRate.add(weightedStableRate).rayDiv(totalDebt.wadToRay());
|
2020-06-20 23:40:03 +00:00
|
|
|
|
|
|
|
return overallBorrowRate;
|
|
|
|
}
|
2020-05-29 16:45:37 +00:00
|
|
|
}
|