2020-05-29 16:45:37 +00:00
|
|
|
// SPDX-License-Identifier: agpl-3.0
|
|
|
|
pragma solidity ^0.6.8;
|
|
|
|
|
2020-08-20 07:51:21 +00:00
|
|
|
import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
|
|
|
|
import {IReserveInterestRateStrategy} from '../interfaces/IReserveInterestRateStrategy.sol';
|
|
|
|
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
|
|
|
|
import {LendingPoolAddressesProvider} from '../configuration/LendingPoolAddressesProvider.sol';
|
|
|
|
import {ILendingRateOracle} from '../interfaces/ILendingRateOracle.sol';
|
2020-05-29 16:45:37 +00:00
|
|
|
|
|
|
|
/**
|
2020-06-20 23:40:03 +00:00
|
|
|
* @title DefaultReserveInterestRateStrategy contract
|
|
|
|
* @notice implements the calculation of the interest rates depending on the reserve parameters.
|
|
|
|
* @dev if there is need to update the calculation of the interest rates for a specific reserve,
|
|
|
|
* a new version of this contract will be deployed.
|
|
|
|
* @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;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev this constant represents the utilization rate at which the pool aims to obtain most competitive borrow rates
|
|
|
|
* expressed in ray
|
|
|
|
**/
|
|
|
|
uint256 public constant OPTIMAL_UTILIZATION_RATE = 0.8 * 1e27;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @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
|
|
|
|
**/
|
|
|
|
|
|
|
|
uint256 public constant EXCESS_UTILIZATION_RATE = 0.2 * 1e27;
|
|
|
|
|
2020-06-27 02:13:32 +00:00
|
|
|
LendingPoolAddressesProvider public immutable addressesProvider;
|
2020-06-20 23:40:03 +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
|
|
|
|
|
|
|
//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
|
|
|
|
|
|
|
//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
|
|
|
|
|
|
|
//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
|
|
|
|
|
|
|
//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-08-21 09:21:50 +00:00
|
|
|
LendingPoolAddressesProvider provider,
|
|
|
|
uint256 baseVariableBorrowRate,
|
|
|
|
uint256 variableRateSlope1,
|
|
|
|
uint256 variableRateSlope2,
|
|
|
|
uint256 stableRateSlope1,
|
|
|
|
uint256 stableRateSlope2
|
2020-06-20 23:40:03 +00:00
|
|
|
) public {
|
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
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev accessors
|
|
|
|
*/
|
|
|
|
|
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-08-24 12:35:59 +00:00
|
|
|
function baseVariableBorrowRate() external override view returns (uint256) {
|
2020-08-21 09:21:50 +00:00
|
|
|
return _baseVariableBorrowRate;
|
2020-06-20 23:40:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev calculates the interest rates depending on the available liquidity and the total borrowed.
|
2020-08-21 09:21:50 +00:00
|
|
|
* @param reserve the address of the reserve
|
|
|
|
* @param availableLiquidity the liquidity available in the reserve
|
|
|
|
* @param totalBorrowsStable the total borrowed from the reserve a stable rate
|
|
|
|
* @param totalBorrowsVariable the total borrowed from the reserve at a variable rate
|
|
|
|
* @param averageStableBorrowRate the weighted average of all the stable rate borrows
|
2020-06-20 23:40:03 +00:00
|
|
|
* @return currentLiquidityRate the liquidity rate
|
|
|
|
* @return currentStableBorrowRate stable borrow rate
|
|
|
|
* @return currentVariableBorrowRate variable borrow rate
|
|
|
|
**/
|
|
|
|
function calculateInterestRates(
|
2020-08-21 09:21:50 +00:00
|
|
|
address reserve,
|
|
|
|
uint256 availableLiquidity,
|
|
|
|
uint256 totalBorrowsStable,
|
|
|
|
uint256 totalBorrowsVariable,
|
|
|
|
uint256 averageStableBorrowRate
|
2020-06-20 23:40:03 +00:00
|
|
|
)
|
|
|
|
external
|
|
|
|
override
|
|
|
|
view
|
|
|
|
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-08-21 09:21:50 +00:00
|
|
|
uint256 totalBorrows = totalBorrowsStable.add(totalBorrowsVariable);
|
|
|
|
uint256 currentVariableBorrowRate = 0;
|
|
|
|
uint256 currentStableBorrowRate = 0;
|
|
|
|
uint256 currentLiquidityRate = 0;
|
2020-06-20 23:40:03 +00:00
|
|
|
|
2020-08-24 12:35:59 +00:00
|
|
|
uint256 utilizationRate = totalBorrows == 0
|
2020-06-20 23:40:03 +00:00
|
|
|
? 0
|
2020-08-21 09:21:50 +00:00
|
|
|
: totalBorrows.rayDiv(availableLiquidity.add(totalBorrows));
|
2020-06-20 23:40:03 +00:00
|
|
|
|
|
|
|
currentStableBorrowRate = ILendingRateOracle(addressesProvider.getLendingRateOracle())
|
2020-08-21 09:21:50 +00:00
|
|
|
.getMarketBorrowRate(reserve);
|
2020-06-20 23:40:03 +00:00
|
|
|
|
|
|
|
if (utilizationRate > OPTIMAL_UTILIZATION_RATE) {
|
|
|
|
uint256 excessUtilizationRateRatio = utilizationRate.sub(OPTIMAL_UTILIZATION_RATE).rayDiv(
|
|
|
|
EXCESS_UTILIZATION_RATE
|
|
|
|
);
|
|
|
|
|
2020-08-21 09:21:50 +00:00
|
|
|
currentStableBorrowRate = currentStableBorrowRate.add(_stableRateSlope1).add(
|
|
|
|
_stableRateSlope2.rayMul(excessUtilizationRateRatio)
|
2020-06-20 23:40:03 +00:00
|
|
|
);
|
|
|
|
|
2020-08-21 09:21:50 +00:00
|
|
|
currentVariableBorrowRate = _baseVariableBorrowRate.add(_variableRateSlope1).add(
|
|
|
|
_variableRateSlope2.rayMul(excessUtilizationRateRatio)
|
2020-06-20 23:40:03 +00:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
currentStableBorrowRate = currentStableBorrowRate.add(
|
2020-08-21 09:21:50 +00:00
|
|
|
_stableRateSlope1.rayMul(utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE))
|
2020-06-20 23:40:03 +00:00
|
|
|
);
|
2020-08-21 09:21:50 +00:00
|
|
|
currentVariableBorrowRate = _baseVariableBorrowRate.add(
|
|
|
|
utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE).rayMul(_variableRateSlope1)
|
2020-06-20 23:40:03 +00:00
|
|
|
);
|
2020-05-29 16:45:37 +00:00
|
|
|
}
|
|
|
|
|
2020-08-21 16:18:12 +00:00
|
|
|
currentLiquidityRate = _getOverallBorrowRate(
|
2020-08-21 09:21:50 +00:00
|
|
|
totalBorrowsStable,
|
|
|
|
totalBorrowsVariable,
|
2020-06-20 23:40:03 +00:00
|
|
|
currentVariableBorrowRate,
|
2020-08-21 09:21:50 +00:00
|
|
|
averageStableBorrowRate
|
2020-06-20 23:40:03 +00:00
|
|
|
)
|
|
|
|
.rayMul(utilizationRate);
|
2020-08-21 09:21:50 +00:00
|
|
|
|
2020-08-24 12:35:59 +00:00
|
|
|
return (currentLiquidityRate, currentStableBorrowRate, currentVariableBorrowRate);
|
2020-06-20 23:40:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev calculates the overall borrow rate as the weighted average between the total variable borrows and total stable borrows.
|
2020-08-21 09:21:50 +00:00
|
|
|
* @param totalBorrowsStable the total borrowed from the reserve a stable rate
|
|
|
|
* @param totalBorrowsVariable the total borrowed from the reserve at a variable rate
|
|
|
|
* @param currentVariableBorrowRate the current variable borrow rate
|
|
|
|
* @param currentAverageStableBorrowRate the weighted average of all the stable rate borrows
|
2020-06-20 23:40:03 +00:00
|
|
|
* @return the weighted averaged borrow rate
|
|
|
|
**/
|
2020-08-21 16:18:12 +00:00
|
|
|
function _getOverallBorrowRate(
|
2020-08-21 09:21:50 +00:00
|
|
|
uint256 totalBorrowsStable,
|
|
|
|
uint256 totalBorrowsVariable,
|
|
|
|
uint256 currentVariableBorrowRate,
|
|
|
|
uint256 currentAverageStableBorrowRate
|
2020-06-20 23:40:03 +00:00
|
|
|
) internal pure returns (uint256) {
|
2020-08-21 09:21:50 +00:00
|
|
|
uint256 totalBorrows = totalBorrowsStable.add(totalBorrowsVariable);
|
2020-06-20 23:40:03 +00:00
|
|
|
|
|
|
|
if (totalBorrows == 0) return 0;
|
|
|
|
|
2020-08-21 09:21:50 +00:00
|
|
|
uint256 weightedVariableRate = totalBorrowsVariable.wadToRay().rayMul(
|
|
|
|
currentVariableBorrowRate
|
2020-06-20 23:40:03 +00:00
|
|
|
);
|
|
|
|
|
2020-08-21 09:21:50 +00:00
|
|
|
uint256 weightedStableRate = totalBorrowsStable.wadToRay().rayMul(
|
|
|
|
currentAverageStableBorrowRate
|
2020-06-20 23:40:03 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
uint256 overallBorrowRate = weightedVariableRate.add(weightedStableRate).rayDiv(
|
|
|
|
totalBorrows.wadToRay()
|
|
|
|
);
|
|
|
|
|
|
|
|
return overallBorrowRate;
|
|
|
|
}
|
2020-05-29 16:45:37 +00:00
|
|
|
}
|