diff --git a/contracts/libraries/ReserveLogic.sol b/contracts/libraries/ReserveLogic.sol index 47cd897e..bc0fe15e 100644 --- a/contracts/libraries/ReserveLogic.sol +++ b/contracts/libraries/ReserveLogic.sol @@ -5,7 +5,7 @@ import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol'; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {MathUtils} from './MathUtils.sol'; import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol'; -import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol'; +import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol'; import {IStableDebtToken} from '../tokenization/interfaces/IStableDebtToken.sol'; import {ReserveConfiguration} from './ReserveConfiguration.sol'; @@ -25,16 +25,35 @@ library ReserveLogic { using SafeMath for uint256; using WadRayMath for uint256; using SafeERC20 for IERC20; - using Address for address; + + /** + * @dev Emitted when the state of a reserve is updated + * @dev NOTE: This event replaces the Deprecated ReserveUpdated() event, which didn't emit the average stable borrow rate + * @param reserve the address of the reserve + * @param liquidityRate the new liquidity rate + * @param stableBorrowRate the new stable borrow rate + * @param averageStableBorrowRate the new average stable borrow rate + * @param variableBorrowRate the new variable borrow rate + * @param liquidityIndex the new liquidity index + * @param variableBorrowIndex the new variable borrow index + **/ + event ReserveDataUpdated( + address indexed reserve, + uint256 liquidityRate, + uint256 stableBorrowRate, + uint256 averageStableBorrowRate, + uint256 variableBorrowRate, + uint256 liquidityIndex, + uint256 variableBorrowIndex + ); + using ReserveLogic for ReserveLogic.ReserveData; using ReserveConfiguration for ReserveConfiguration.Map; enum InterestRateMode {NONE, STABLE, VARIABLE} + // refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties. struct ReserveData { - /** - * @dev refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties. - **/ //the liquidity index. Expressed in ray uint256 lastLiquidityCumulativeIndex; //the current supply rate. Expressed in ray @@ -45,27 +64,21 @@ library ReserveLogic { uint256 currentStableBorrowRate; //variable borrow index. Expressed in ray uint256 lastVariableBorrowCumulativeIndex; + //stores the reserve configuration ReserveConfiguration.Map configuration; - /** - * @dev address of the aToken representing the asset - **/ address payable aTokenAddress; address stableDebtTokenAddress; address variableDebtTokenAddress; - /** - * @dev address of the interest rate strategy contract - **/ address interestRateStrategyAddress; uint40 lastUpdateTimestamp; - // isStableBorrowRateEnabled = true means users can borrow at a stable rate - bool isStableBorrowRateEnabled; + //the index of the reserve in the list of the active reserves uint8 index; } /** * @dev returns the ongoing normalized income for the reserve. * a value of 1e27 means there is no income. As time passes, the income is accrued. - * A value of 2*1e27 means that the income of the reserve is double the initial amount. + * A value of 2*1e27 means for each unit of assset two units of income have been accrued. * @param _reserve the reserve object * @return the normalized income. expressed in ray **/ @@ -114,10 +127,11 @@ library ReserveLogic { * @param _self the reserve object **/ function updateCumulativeIndexesAndTimestamp(ReserveData storage _self) internal { - uint256 totalBorrows = getTotalBorrows(_self); - - if (totalBorrows > 0) { - //only cumulating if there is any income being produced + //only cumulating if there is any income being produced + if ( + IERC20(_self.variableDebtTokenAddress).totalSupply() > 0 || + IERC20(_self.stableDebtTokenAddress).totalSupply() > 0 + ) { uint256 cumulatedLiquidityInterest = MathUtils.calculateLinearInterest( _self.currentLiquidityRate, _self.lastUpdateTimestamp @@ -190,34 +204,6 @@ library ReserveLogic { _self.interestRateStrategyAddress = _interestRateStrategyAddress; } - function getTotalBorrows(ReserveData storage _self) internal view returns (uint256) { - return - IERC20(_self.stableDebtTokenAddress).totalSupply().add( - IERC20(_self.variableDebtTokenAddress).totalSupply() - ); - } - - /** - * @dev Emitted when the state of a reserve is updated - * @dev NOTE: This event replaces the Deprecated ReserveUpdated() event, which didn't emit the average stable borrow rate - * @param reserve the address of the reserve - * @param liquidityRate the new liquidity rate - * @param stableBorrowRate the new stable borrow rate - * @param averageStableBorrowRate the new average stable borrow rate - * @param variableBorrowRate the new variable borrow rate - * @param liquidityIndex the new liquidity index - * @param variableBorrowIndex the new variable borrow index - **/ - event ReserveDataUpdated( - address indexed reserve, - uint256 liquidityRate, - uint256 stableBorrowRate, - uint256 averageStableBorrowRate, - uint256 variableBorrowRate, - uint256 liquidityIndex, - uint256 variableBorrowIndex - ); - /** * @dev updates the state of the core as a result of a flashloan action * @param _reserve the address of the reserve in which the flashloan is happening @@ -233,7 +219,9 @@ library ReserveLogic { //compounding the cumulated interest _reserve.updateCumulativeIndexesAndTimestamp(); - uint256 totalLiquidityBefore = _availableLiquidityBefore.add(_reserve.getTotalBorrows()); + uint256 totalLiquidityBefore = _availableLiquidityBefore + .add(IERC20(_reserve.variableDebtTokenAddress).totalSupply()) + .add(IERC20(_reserve.stableDebtTokenAddress).totalSupply()); //compounding the received fee into the reserve _reserve.cumulateToLiquidityIndex(totalLiquidityBefore, _income); @@ -242,20 +230,6 @@ library ReserveLogic { updateInterestRates(_reserve, _reserveAddress, _income, 0); } - /** - * @dev gets the total liquidity in the reserve. The total liquidity is the balance of the core contract + total borrows - * @param _reserve the reserve address - * @return the total liquidity - **/ - function getTotalLiquidity(ReserveData storage _reserve, address _reserveAddress) - public - view - returns (uint256) - { - return - IERC20(_reserveAddress).balanceOf(address(this)).add(_reserve.getTotalBorrows()); - } - /** * @dev Updates the reserve current stable borrow rate Rf, the current variable borrow rate Rv and the current liquidity rate Rl. * Also updates the lastUpdateTimestamp value. Please refer to the whitepaper for further information. @@ -300,56 +274,4 @@ library ReserveLogic { _reserve.lastVariableBorrowCumulativeIndex ); } - - /** - * @dev gets the reserve current variable borrow rate. Is the base variable borrow rate if the reserve is empty - * @param _reserve the reserve address - * @return the reserve current variable borrow rate - **/ - function getReserveCurrentVariableBorrowRate(ReserveData storage _reserve) - external - view - returns (uint256) - { - if (_reserve.currentVariableBorrowRate == 0) { - return - IReserveInterestRateStrategy(_reserve.interestRateStrategyAddress) - .getBaseVariableBorrowRate(); - } - return _reserve.currentVariableBorrowRate; - } - - /** - * @dev gets the reserve current stable borrow rate. Is the market rate if the reserve is empty - * @param _reserve the reserve address - * @return the reserve current stable borrow rate - **/ - function getReserveCurrentStableBorrowRate(ReserveData storage _reserve, uint256 _baseRate) - public - view - returns (uint256) - { - return _reserve.currentStableBorrowRate == 0 ? _baseRate : _reserve.currentStableBorrowRate; - } - - /** - * @dev returns the utilization rate U of a specific reserve - * @param _reserve the reserve for which the information is needed - * @return the utilization rate in ray - **/ - function getUtilizationRate(ReserveData storage _reserve, address _reserveAddress) - public - view - returns (uint256) - { - uint256 totalBorrows = _reserve.getTotalBorrows(); - - if (totalBorrows == 0) { - return 0; - } - - uint256 availableLiquidity = IERC20(_reserveAddress).balanceOf(address(this)); - - return totalBorrows.rayDiv(availableLiquidity.add(totalBorrows)); - } }