aave-protocol-v2/contracts/lendingpool/DefaultReserveInterestRateStrategy.sol

191 lines
6.9 KiB
Solidity

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
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';
/**
* @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
**/
contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
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;
LendingPoolAddressesProvider public immutable addressesProvider;
//base variable borrow rate when Utilization rate = 0. Expressed in ray
uint256 internal immutable baseVariableBorrowRate;
//slope of the variable interest curve when utilization rate > 0 and <= OPTIMAL_UTILIZATION_RATE. Expressed in ray
uint256 internal immutable variableRateSlope1;
//slope of the variable interest curve when utilization rate > OPTIMAL_UTILIZATION_RATE. Expressed in ray
uint256 internal immutable variableRateSlope2;
//slope of the stable interest curve when utilization rate > 0 and <= OPTIMAL_UTILIZATION_RATE. Expressed in ray
uint256 internal immutable stableRateSlope1;
//slope of the stable interest curve when utilization rate > OPTIMAL_UTILIZATION_RATE. Expressed in ray
uint256 internal immutable stableRateSlope2;
constructor(
LendingPoolAddressesProvider _provider,
uint256 _baseVariableBorrowRate,
uint256 _variableRateSlope1,
uint256 _variableRateSlope2,
uint256 _stableRateSlope1,
uint256 _stableRateSlope2
) public {
addressesProvider = _provider;
baseVariableBorrowRate = _baseVariableBorrowRate;
variableRateSlope1 = _variableRateSlope1;
variableRateSlope2 = _variableRateSlope2;
stableRateSlope1 = _stableRateSlope1;
stableRateSlope2 = _stableRateSlope2;
}
/**
* @dev accessors
*/
function getVariableRateSlope1() external view returns (uint256) {
return variableRateSlope1;
}
function getVariableRateSlope2() external view returns (uint256) {
return variableRateSlope2;
}
function getStableRateSlope1() external view returns (uint256) {
return stableRateSlope1;
}
function getStableRateSlope2() external view returns (uint256) {
return stableRateSlope2;
}
function getBaseVariableBorrowRate() external override view returns (uint256) {
return baseVariableBorrowRate;
}
/**
* @dev calculates the interest rates depending on the available liquidity and the total borrowed.
* @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
* @return currentLiquidityRate the liquidity rate
* @return currentStableBorrowRate stable borrow rate
* @return currentVariableBorrowRate variable borrow rate
**/
function calculateInterestRates(
address _reserve,
uint256 _availableLiquidity,
uint256 _totalBorrowsStable,
uint256 _totalBorrowsVariable,
uint256 _averageStableBorrowRate
)
external
override
view
returns (
uint256 currentLiquidityRate,
uint256 currentStableBorrowRate,
uint256 currentVariableBorrowRate
)
{
uint256 totalBorrows = _totalBorrowsStable.add(_totalBorrowsVariable);
uint256 utilizationRate = (totalBorrows == 0 && _availableLiquidity == 0)
? 0
: totalBorrows.rayDiv(_availableLiquidity.add(totalBorrows));
currentStableBorrowRate = ILendingRateOracle(addressesProvider.getLendingRateOracle())
.getMarketBorrowRate(_reserve);
if (utilizationRate > OPTIMAL_UTILIZATION_RATE) {
uint256 excessUtilizationRateRatio = utilizationRate.sub(OPTIMAL_UTILIZATION_RATE).rayDiv(
EXCESS_UTILIZATION_RATE
);
currentStableBorrowRate = currentStableBorrowRate.add(stableRateSlope1).add(
stableRateSlope2.rayMul(excessUtilizationRateRatio)
);
currentVariableBorrowRate = baseVariableBorrowRate.add(variableRateSlope1).add(
variableRateSlope2.rayMul(excessUtilizationRateRatio)
);
} else {
currentStableBorrowRate = currentStableBorrowRate.add(
stableRateSlope1.rayMul(utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE))
);
currentVariableBorrowRate = baseVariableBorrowRate.add(
utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE).rayMul(variableRateSlope1)
);
}
currentLiquidityRate = getOverallBorrowRateInternal(
_totalBorrowsStable,
_totalBorrowsVariable,
currentVariableBorrowRate,
_averageStableBorrowRate
)
.rayMul(utilizationRate);
}
/**
* @dev calculates the overall borrow rate as the weighted average between the total variable borrows and total stable borrows.
* @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
* @return the weighted averaged borrow rate
**/
function getOverallBorrowRateInternal(
uint256 _totalBorrowsStable,
uint256 _totalBorrowsVariable,
uint256 _currentVariableBorrowRate,
uint256 _currentAverageStableBorrowRate
) internal pure returns (uint256) {
uint256 totalBorrows = _totalBorrowsStable.add(_totalBorrowsVariable);
if (totalBorrows == 0) return 0;
uint256 weightedVariableRate = _totalBorrowsVariable.wadToRay().rayMul(
_currentVariableBorrowRate
);
uint256 weightedStableRate = _totalBorrowsStable.wadToRay().rayMul(
_currentAverageStableBorrowRate
);
uint256 overallBorrowRate = weightedVariableRate.add(weightedStableRate).rayDiv(
totalBorrows.wadToRay()
);
return overallBorrowRate;
}
}