Contract detail
DefaultReserveInterestRateStrategy
DefaultReserveInterestRateStrategy is a verified Robinhood Chain smart contract at 0xc93712d8…caed7c2d with 0 indexed transactions.
- Address type
- Smart contract
- Transactions
- 0
- History coverage
- No indexed activity found
- Verification
- Verified
- Compiler
- v0.8.10+commit.fc410830
- Verification match
- full
- Creation transaction
- 0xdb2c1842…e03b7d37
- Created at block
- #899646
- Language
- solidity
- EVM version
- berlin
- License
- none
- Compiler optimization
- Enabled · 100000 runs
Verified contract
Contract source code
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.10;
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {PercentageMath} from '../libraries/math/PercentageMath.sol';
import {DataTypes} from '../libraries/types/DataTypes.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
import {IDefaultInterestRateStrategy} from '../../interfaces/IDefaultInterestRateStrategy.sol';
import {IReserveInterestRateStrategy} from '../../interfaces/IReserveInterestRateStrategy.sol';
import {IPoolAddressesProvider} from '../../interfaces/IPoolAddressesProvider.sol';
/**
* @title DefaultReserveInterestRateStrategy contract
* @author Aave
* @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_USAGE_RATIO`
* point of usage 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 PoolAddressesProvider
*/
contract DefaultReserveInterestRateStrategy is IDefaultInterestRateStrategy {
using WadRayMath for uint256;
using PercentageMath for uint256;
/// @inheritdoc IDefaultInterestRateStrategy
uint256 public immutable OPTIMAL_USAGE_RATIO;
/// @inheritdoc IDefaultInterestRateStrategy
uint256 public immutable OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO;
/// @inheritdoc IDefaultInterestRateStrategy
uint256 public immutable MAX_EXCESS_USAGE_RATIO;
/// @inheritdoc IDefaultInterestRateStrategy
uint256 public immutable MAX_EXCESS_STABLE_TO_TOTAL_DEBT_RATIO;
IPoolAddressesProvider public immutable ADDRESSES_PROVIDER;
// Base variable borrow rate when usage rate = 0. Expressed in ray
uint256 internal immutable _baseVariableBorrowRate;
// Slope of the variable interest curve when usage ratio > 0 and <= OPTIMAL_USAGE_RATIO. Expressed in ray
uint256 internal immutable _variableRateSlope1;
// Slope of the variable interest curve when usage ratio > OPTIMAL_USAGE_RATIO. Expressed in ray
uint256 internal immutable _variableRateSlope2;
// Slope of the stable interest curve when usage ratio > 0 and <= OPTIMAL_USAGE_RATIO. Expressed in ray
uint256 internal immutable _stableRateSlope1;
// Slope of the stable interest curve when usage ratio > OPTIMAL_USAGE_RATIO. Expressed in ray
uint256 internal immutable _stableRateSlope2;
// Premium on top of `_variableRateSlope1` for base stable borrowing rate
uint256 internal immutable _baseStableRateOffset;
// Additional premium applied to stable rate when stable debt surpass `OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO`
uint256 internal immutable _stableRateExcessOffset;
/**
* @dev Constructor.
* @param provider The address of the PoolAddressesProvider contract
* @param optimalUsageRatio The optimal usage ratio
* @param baseVariableBorrowRate The base variable borrow rate
* @param variableRateSlope1 The variable rate slope below optimal usage ratio
* @param variableRateSlope2 The variable rate slope above optimal usage ratio
* @param stableRateSlope1 The stable rate slope below optimal usage ratio
* @param stableRateSlope2 The stable rate slope above optimal usage ratio
* @param baseStableRateOffset The premium on top of variable rate for base stable borrowing rate
* @param stableRateExcessOffset The premium on top of stable rate when there stable debt surpass the threshold
* @param optimalStableToTotalDebtRatio The optimal stable debt to total debt ratio of the reserve
*/
constructor(
IPoolAddressesProvider provider,
uint256 optimalUsageRatio,
uint256 baseVariableBorrowRate,
uint256 variableRateSlope1,
uint256 variableRateSlope2,
uint256 stableRateSlope1,
uint256 stableRateSlope2,
uint256 baseStableRateOffset,
uint256 stableRateExcessOffset,
uint256 optimalStableToTotalDebtRatio
) {
require(WadRayMath.RAY >= optimalUsageRatio, Errors.INVALID_OPTIMAL_USAGE_RATIO);
require(
WadRayMath.RAY >= optimalStableToTotalDebtRatio,
Errors.INVALID_OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO
);
OPTIMAL_USAGE_RATIO = optimalUsageRatio;
MAX_EXCESS_USAGE_RATIO = WadRayMath.RAY - optimalUsageRatio;
OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO = optimalStableToTotalDebtRatio;
MAX_EXCESS_STABLE_TO_TOTAL_DEBT_RATIO = WadRayMath.RAY - optimalStableToTotalDebtRatio;
ADDRESSES_PROVIDER = provider;
_baseVariableBorrowRate = baseVariableBorrowRate;
_variableRateSlope1 = variableRateSlope1;
_variableRateSlope2 = variableRateSlope2;
_stableRateSlope1 = stableRateSlope1;
_stableRateSlope2 = stableRateSlope2;
_baseStableRateOffset = baseStableRateOffset;
_stableRateExcessOffset = stableRateExcessOffset;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getVariableRateSlope1() external view returns (uint256) {
return _variableRateSlope1;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getVariableRateSlope2() external view returns (uint256) {
return _variableRateSlope2;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getStableRateSlope1() external view returns (uint256) {
return _stableRateSlope1;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getStableRateSlope2() external view returns (uint256) {
return _stableRateSlope2;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getStableRateExcessOffset() external view returns (uint256) {
return _stableRateExcessOffset;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getBaseStableBorrowRate() public view returns (uint256) {
return _variableRateSlope1 + _baseStableRateOffset;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getBaseVariableBorrowRate() external view override returns (uint256) {
return _baseVariableBorrowRate;
}
/// @inheritdoc IDefaultInterestRateStrategy
function getMaxVariableBorrowRate() external view override returns (uint256) {
return _baseVariableBorrowRate + _variableRateSlope1 + _variableRateSlope2;
}
struct CalcInterestRatesLocalVars {
uint256 availableLiquidity;
uint256 totalDebt;
uint256 currentVariableBorrowRate;
uint256 currentStableBorrowRate;
uint256 currentLiquidityRate;
uint256 borrowUsageRatio;
uint256 supplyUsageRatio;
uint256 stableToTotalDebtRatio;
uint256 availableLiquidityPlusDebt;
}
/// @inheritdoc IReserveInterestRateStrategy
function calculateInterestRates(
DataTypes.CalculateInterestRatesParams memory params
) public view override returns (uint256, uint256, uint256) {
CalcInterestRatesLocalVars memory vars;
vars.totalDebt = params.totalStableDebt + params.totalVariableDebt;
vars.currentLiquidityRate = 0;
vars.currentVariableBorrowRate = _baseVariableBorrowRate;
vars.currentStableBorrowRate = getBaseStableBorrowRate();
if (vars.totalDebt != 0) {
vars.stableToTotalDebtRatio = params.totalStableDebt.rayDiv(vars.totalDebt);
vars.availableLiquidity =
IERC20(params.reserve).balanceOf(params.aToken) +
params.liquidityAdded -
params.liquidityTaken;
vars.availableLiquidityPlusDebt = vars.availableLiquidity + vars.totalDebt;
vars.borrowUsageRatio = vars.totalDebt.rayDiv(vars.availableLiquidityPlusDebt);
vars.supplyUsageRatio = vars.totalDebt.rayDiv(
vars.availableLiquidityPlusDebt + params.unbacked
);
}
if (vars.borrowUsageRatio > OPTIMAL_USAGE_RATIO) {
uint256 excessBorrowUsageRatio = (vars.borrowUsageRatio - OPTIMAL_USAGE_RATIO).rayDiv(
MAX_EXCESS_USAGE_RATIO
);
vars.currentStableBorrowRate +=
_stableRateSlope1 +
_stableRateSlope2.rayMul(excessBorrowUsageRatio);
vars.currentVariableBorrowRate +=
_variableRateSlope1 +
_variableRateSlope2.rayMul(excessBorrowUsageRatio);
} else {
vars.currentStableBorrowRate += _stableRateSlope1.rayMul(vars.borrowUsageRatio).rayDiv(
OPTIMAL_USAGE_RATIO
);
vars.currentVariableBorrowRate += _variableRateSlope1.rayMul(vars.borrowUsageRatio).rayDiv(
OPTIMAL_USAGE_RATIO
);
}
if (vars.stableToTotalDebtRatio > OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO) {
uint256 excessStableDebtRatio = (vars.stableToTotalDebtRatio -
OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO).rayDiv(MAX_EXCESS_STABLE_TO_TOTAL_DEBT_RATIO);
vars.currentStableBorrowRate += _stableRateExcessOffset.rayMul(excessStableDebtRatio);
}
vars.currentLiquidityRate = _getOverallBorrowRate(
params.totalStableDebt,
params.totalVariableDebt,
vars.currentVariableBorrowRate,
params.averageStableBorrowRate
).rayMul(vars.supplyUsageRatio).percentMul(
PercentageMath.PERCENTAGE_FACTOR - params.reserveFactor
);
return (
vars.currentLiquidityRate,
vars.currentStableBorrowRate,
vars.currentVariableBorrowRate
);
}
/**
* @dev Calculates the overall borrow rate as the weighted average between the total variable debt and total stable
* debt
* @param totalStableDebt The total borrowed from the reserve at 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
*/
function _getOverallBorrowRate(
uint256 totalStableDebt,
uint256 totalVariableDebt,
uint256 currentVariableBorrowRate,
uint256 currentAverageStableBorrowRate
) internal pure returns (uint256) {
uint256 totalDebt = totalStableDebt + totalVariableDebt;
if (totalDebt == 0) return 0;
uint256 weightedVariableRate = totalVariableDebt.wadToRay().rayMul(currentVariableBorrowRate);
uint256 weightedStableRate = totalStableDebt.wadToRay().rayMul(currentAverageStableBorrowRate);
uint256 overallBorrowRate = (weightedVariableRate + weightedStableRate).rayDiv(
totalDebt.wadToRay()
);
return overallBorrowRate;
}
}