LCOV - code coverage report
Current view: top level - misc - DefaultReserveInterestRateStrategyV2.sol (source / functions) Coverage Total Hit
Test: lcov.info.p Lines: 100.0 % 39 39
Test Date: 2024-09-24 09:34:24 Functions: 100.0 % 14 14
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : // SPDX-License-Identifier: MIT
       2                 :             : pragma solidity ^0.8.0;
       3                 :             : 
       4                 :             : import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
       5                 :             : import {WadRayMath} from '../protocol/libraries/math/WadRayMath.sol';
       6                 :             : import {PercentageMath} from '../protocol/libraries/math/PercentageMath.sol';
       7                 :             : import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
       8                 :             : import {Errors} from '../protocol/libraries/helpers/Errors.sol';
       9                 :             : import {IDefaultInterestRateStrategyV2} from '../interfaces/IDefaultInterestRateStrategyV2.sol';
      10                 :             : import {IReserveInterestRateStrategy} from '../interfaces/IReserveInterestRateStrategy.sol';
      11                 :             : import {IPoolAddressesProvider} from '../interfaces/IPoolAddressesProvider.sol';
      12                 :             : 
      13                 :             : /**
      14                 :             :  * @title DefaultReserveInterestRateStrategyV2 contract
      15                 :             :  * @author BGD Labs
      16                 :             :  * @notice Default interest rate strategy used by the Aave protocol
      17                 :             :  * @dev Strategies are pool-specific: each contract CAN'T be used across different Aave pools
      18                 :             :  *   due to the caching of the PoolAddressesProvider and the usage of underlying addresses as
      19                 :             :  *   index of the _interestRateData
      20                 :             :  */
      21                 :             : contract DefaultReserveInterestRateStrategyV2 is IDefaultInterestRateStrategyV2 {
      22                 :             :   using WadRayMath for uint256;
      23                 :             :   using PercentageMath for uint256;
      24                 :             : 
      25                 :             :   struct CalcInterestRatesLocalVars {
      26                 :             :     uint256 availableLiquidity;
      27                 :             :     uint256 currentVariableBorrowRate;
      28                 :             :     uint256 currentLiquidityRate;
      29                 :             :     uint256 borrowUsageRatio;
      30                 :             :     uint256 supplyUsageRatio;
      31                 :             :     uint256 availableLiquidityPlusDebt;
      32                 :             :   }
      33                 :             : 
      34                 :             :   /// @inheritdoc IDefaultInterestRateStrategyV2
      35                 :             :   IPoolAddressesProvider public immutable ADDRESSES_PROVIDER;
      36                 :             : 
      37                 :             :   /// @inheritdoc IDefaultInterestRateStrategyV2
      38                 :             :   uint256 public constant MAX_BORROW_RATE = 1000_00;
      39                 :             : 
      40                 :             :   /// @inheritdoc IDefaultInterestRateStrategyV2
      41                 :             :   uint256 public constant MIN_OPTIMAL_POINT = 1_00;
      42                 :             : 
      43                 :             :   /// @inheritdoc IDefaultInterestRateStrategyV2
      44                 :             :   uint256 public constant MAX_OPTIMAL_POINT = 99_00;
      45                 :             : 
      46                 :             :   /// @dev Map of reserves address and their interest rate data (reserveAddress => interestRateData)
      47                 :             :   mapping(address => InterestRateData) internal _interestRateData;
      48                 :             : 
      49                 :             :   modifier onlyPoolConfigurator() {
      50                 :      190067 :     require(
      51                 :             :       msg.sender == ADDRESSES_PROVIDER.getPoolConfigurator(),
      52                 :             :       Errors.CALLER_NOT_POOL_CONFIGURATOR
      53                 :             :     );
      54                 :             :     _;
      55                 :             :   }
      56                 :             : 
      57                 :             :   /**
      58                 :             :    * @dev Constructor.
      59                 :             :    * @param provider The address of the PoolAddressesProvider of the associated Aave pool
      60                 :             :    */
      61                 :             :   constructor(address provider) {
      62                 :         147 :     require(provider != address(0), Errors.INVALID_ADDRESSES_PROVIDER);
      63                 :         165 :     ADDRESSES_PROVIDER = IPoolAddressesProvider(provider);
      64                 :             :   }
      65                 :             : 
      66                 :             :   /// @inheritdoc IReserveInterestRateStrategy
      67                 :             :   function setInterestRateParams(
      68                 :             :     address reserve,
      69                 :             :     bytes calldata rateData
      70                 :             :   ) external onlyPoolConfigurator {
      71                 :      188067 :     _setInterestRateParams(reserve, abi.decode(rateData, (InterestRateData)));
      72                 :             :   }
      73                 :             : 
      74                 :             :   /// @inheritdoc IDefaultInterestRateStrategyV2
      75                 :             :   function setInterestRateParams(
      76                 :             :     address reserve,
      77                 :             :     InterestRateData calldata rateData
      78                 :             :   ) external onlyPoolConfigurator {
      79                 :       10000 :     _setInterestRateParams(reserve, rateData);
      80                 :             :   }
      81                 :             : 
      82                 :             :   /// @inheritdoc IDefaultInterestRateStrategyV2
      83                 :             :   function getInterestRateData(address reserve) external view returns (InterestRateDataRay memory) {
      84                 :        1000 :     return _rayifyRateData(_interestRateData[reserve]);
      85                 :             :   }
      86                 :             : 
      87                 :             :   /// @inheritdoc IDefaultInterestRateStrategyV2
      88                 :             :   function getInterestRateDataBps(address reserve) external view returns (InterestRateData memory) {
      89                 :        1000 :     return _interestRateData[reserve];
      90                 :             :   }
      91                 :             : 
      92                 :             :   /// @inheritdoc IDefaultInterestRateStrategyV2
      93                 :             :   function getOptimalUsageRatio(address reserve) external view returns (uint256) {
      94                 :        8088 :     return _bpsToRay(uint256(_interestRateData[reserve].optimalUsageRatio));
      95                 :             :   }
      96                 :             : 
      97                 :             :   /// @inheritdoc IDefaultInterestRateStrategyV2
      98                 :             :   function getVariableRateSlope1(address reserve) external view returns (uint256) {
      99                 :        8092 :     return _bpsToRay(uint256(_interestRateData[reserve].variableRateSlope1));
     100                 :             :   }
     101                 :             : 
     102                 :             :   /// @inheritdoc IDefaultInterestRateStrategyV2
     103                 :             :   function getVariableRateSlope2(address reserve) external view returns (uint256) {
     104                 :        5088 :     return _bpsToRay(uint256(_interestRateData[reserve].variableRateSlope2));
     105                 :             :   }
     106                 :             : 
     107                 :             :   /// @inheritdoc IDefaultInterestRateStrategyV2
     108                 :             :   function getBaseVariableBorrowRate(address reserve) external view override returns (uint256) {
     109                 :       11092 :     return _bpsToRay(uint256(_interestRateData[reserve].baseVariableBorrowRate));
     110                 :             :   }
     111                 :             : 
     112                 :             :   /// @inheritdoc IDefaultInterestRateStrategyV2
     113                 :             :   function getMaxVariableBorrowRate(address reserve) external view override returns (uint256) {
     114                 :        5084 :     return
     115                 :        5084 :       _bpsToRay(
     116                 :             :         uint256(
     117                 :             :           _interestRateData[reserve].baseVariableBorrowRate +
     118                 :             :             _interestRateData[reserve].variableRateSlope1 +
     119                 :             :             _interestRateData[reserve].variableRateSlope2
     120                 :             :         )
     121                 :             :       );
     122                 :             :   }
     123                 :             : 
     124                 :             :   /// @inheritdoc IReserveInterestRateStrategy
     125                 :             :   function calculateInterestRates(
     126                 :             :     DataTypes.CalculateInterestRatesParams memory params
     127                 :             :   ) external view virtual override returns (uint256, uint256) {
     128                 :       92717 :     InterestRateDataRay memory rateData = _rayifyRateData(_interestRateData[params.reserve]);
     129                 :             : 
     130                 :             :     // @note This is a short circuit to allow mintable assets (ex. GHO), which by definition cannot be supplied
     131                 :             :     // and thus do not use virtual underlying balances.
     132                 :       92717 :     if (!params.usingVirtualBalance) {
     133                 :        1000 :       return (0, rateData.baseVariableBorrowRate);
     134                 :             :     }
     135                 :             : 
     136                 :       91717 :     CalcInterestRatesLocalVars memory vars;
     137                 :             : 
     138                 :       91717 :     vars.currentLiquidityRate = 0;
     139                 :       91717 :     vars.currentVariableBorrowRate = rateData.baseVariableBorrowRate;
     140                 :             : 
     141                 :       91717 :     if (params.totalDebt != 0) {
     142                 :       32099 :       vars.availableLiquidity =
     143                 :             :         params.virtualUnderlyingBalance +
     144                 :             :         params.liquidityAdded -
     145                 :             :         params.liquidityTaken;
     146                 :             : 
     147                 :       32098 :       vars.availableLiquidityPlusDebt = vars.availableLiquidity + params.totalDebt;
     148                 :       32098 :       vars.borrowUsageRatio = params.totalDebt.rayDiv(vars.availableLiquidityPlusDebt);
     149                 :       32098 :       vars.supplyUsageRatio = params.totalDebt.rayDiv(
     150                 :             :         vars.availableLiquidityPlusDebt + params.unbacked
     151                 :             :       );
     152                 :             :     } else {
     153                 :       59618 :       return (0, vars.currentVariableBorrowRate);
     154                 :             :     }
     155                 :             : 
     156                 :       32098 :     if (vars.borrowUsageRatio > rateData.optimalUsageRatio) {
     157                 :        6390 :       uint256 excessBorrowUsageRatio = (vars.borrowUsageRatio - rateData.optimalUsageRatio).rayDiv(
     158                 :             :         WadRayMath.RAY - rateData.optimalUsageRatio
     159                 :             :       );
     160                 :             : 
     161                 :        6390 :       vars.currentVariableBorrowRate +=
     162                 :             :         rateData.variableRateSlope1 +
     163                 :             :         rateData.variableRateSlope2.rayMul(excessBorrowUsageRatio);
     164                 :             :     } else {
     165                 :       25708 :       vars.currentVariableBorrowRate += rateData
     166                 :             :         .variableRateSlope1
     167                 :             :         .rayMul(vars.borrowUsageRatio)
     168                 :             :         .rayDiv(rateData.optimalUsageRatio);
     169                 :             :     }
     170                 :             : 
     171                 :       32098 :     vars.currentLiquidityRate = vars
     172                 :             :       .currentVariableBorrowRate
     173                 :             :       .rayMul(vars.supplyUsageRatio)
     174                 :             :       .percentMul(PercentageMath.PERCENTAGE_FACTOR - params.reserveFactor);
     175                 :             : 
     176                 :       32098 :     return (vars.currentLiquidityRate, vars.currentVariableBorrowRate);
     177                 :             :   }
     178                 :             : 
     179                 :             :   /**
     180                 :             :    * @dev Doing validations and data update for an asset
     181                 :             :    * @param reserve address of the underlying asset of the reserve
     182                 :             :    * @param rateData Encoded reserve interest rate data to apply
     183                 :             :    */
     184                 :             :   function _setInterestRateParams(address reserve, InterestRateData memory rateData) internal {
     185                 :      198067 :     require(reserve != address(0), Errors.ZERO_ADDRESS_NOT_VALID);
     186                 :             : 
     187                 :      194067 :     require(
     188                 :             :       rateData.optimalUsageRatio <= MAX_OPTIMAL_POINT &&
     189                 :             :         rateData.optimalUsageRatio >= MIN_OPTIMAL_POINT,
     190                 :             :       Errors.INVALID_OPTIMAL_USAGE_RATIO
     191                 :             :     );
     192                 :             : 
     193                 :      186067 :     require(
     194                 :             :       rateData.variableRateSlope1 <= rateData.variableRateSlope2,
     195                 :             :       Errors.SLOPE_2_MUST_BE_GTE_SLOPE_1
     196                 :             :     );
     197                 :             : 
     198                 :             :     // The maximum rate should not be above certain threshold
     199                 :      182067 :     require(
     200                 :             :       uint256(rateData.baseVariableBorrowRate) +
     201                 :             :         uint256(rateData.variableRateSlope1) +
     202                 :             :         uint256(rateData.variableRateSlope2) <=
     203                 :             :         MAX_BORROW_RATE,
     204                 :             :       Errors.INVALID_MAX_RATE
     205                 :             :     );
     206                 :             : 
     207                 :      178067 :     _interestRateData[reserve] = rateData;
     208                 :      178067 :     emit RateDataUpdate(
     209                 :             :       reserve,
     210                 :             :       rateData.optimalUsageRatio,
     211                 :             :       rateData.baseVariableBorrowRate,
     212                 :             :       rateData.variableRateSlope1,
     213                 :             :       rateData.variableRateSlope2
     214                 :             :     );
     215                 :             :   }
     216                 :             : 
     217                 :             :   /**
     218                 :             :    * @dev Transforms an InterestRateData struct to an InterestRateDataRay struct by multiplying all values
     219                 :             :    * by 1e23, turning them into ray values
     220                 :             :    *
     221                 :             :    * @param data The InterestRateData struct to transform
     222                 :             :    *
     223                 :             :    * @return The resulting InterestRateDataRay struct
     224                 :             :    */
     225                 :             :   function _rayifyRateData(
     226                 :             :     InterestRateData memory data
     227                 :             :   ) internal pure returns (InterestRateDataRay memory) {
     228                 :       93717 :     return
     229                 :             :       InterestRateDataRay({
     230                 :             :         optimalUsageRatio: _bpsToRay(uint256(data.optimalUsageRatio)),
     231                 :             :         baseVariableBorrowRate: _bpsToRay(uint256(data.baseVariableBorrowRate)),
     232                 :             :         variableRateSlope1: _bpsToRay(uint256(data.variableRateSlope1)),
     233                 :             :         variableRateSlope2: _bpsToRay(uint256(data.variableRateSlope2))
     234                 :             :       });
     235                 :             :   }
     236                 :             : 
     237                 :             :   // @dev helper function added here, as generally the protocol doesn't use bps
     238                 :             :   function _bpsToRay(uint256 n) internal pure returns (uint256) {
     239                 :      412312 :     return n * 1e23;
     240                 :             :   }
     241                 :             : }
        

Generated by: LCOV version 2.1-1