mirror of
				https://github.com/Instadapp/aave-protocol-v2.git
				synced 2024-07-29 21:47:30 +00:00 
			
		
		
		
	feat: initial cache layer implementation
This commit is contained in:
		
							parent
							
								
									729194d587
								
							
						
					
					
						commit
						6cdfd8e31b
					
				|  | @ -26,6 +26,7 @@ import {ReserveConfiguration} from '../libraries/configuration/ReserveConfigurat | |||
| import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol'; | ||||
| import {DataTypes} from '../libraries/types/DataTypes.sol'; | ||||
| import {LendingPoolStorage} from './LendingPoolStorage.sol'; | ||||
| import {CachingHelper} from '../libraries/helpers/CachingHelper.sol'; | ||||
| 
 | ||||
| /** | ||||
|  * @title LendingPool contract | ||||
|  | @ -270,6 +271,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
|    **/ | ||||
|   function swapBorrowRateMode(address asset, uint256 rateMode) external override whenNotPaused { | ||||
|     DataTypes.ReserveData storage reserve = _reserves[asset]; | ||||
|     CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve); | ||||
| 
 | ||||
|     (uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve); | ||||
| 
 | ||||
|  | @ -283,7 +285,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
|       interestRateMode | ||||
|     ); | ||||
| 
 | ||||
|     reserve.updateState(); | ||||
|     reserve.updateState(cachedData); | ||||
| 
 | ||||
|     if (interestRateMode == DataTypes.InterestRateMode.STABLE) { | ||||
|       IStableDebtToken(reserve.stableDebtTokenAddress).burn(msg.sender, stableDebt); | ||||
|  | @ -323,6 +325,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
|    **/ | ||||
|   function rebalanceStableBorrowRate(address asset, address user) external override whenNotPaused { | ||||
|     DataTypes.ReserveData storage reserve = _reserves[asset]; | ||||
|     CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve); | ||||
| 
 | ||||
|     IERC20 stableDebtToken = IERC20(reserve.stableDebtTokenAddress); | ||||
|     IERC20 variableDebtToken = IERC20(reserve.variableDebtTokenAddress); | ||||
|  | @ -338,7 +341,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
|       aTokenAddress | ||||
|     ); | ||||
| 
 | ||||
|     reserve.updateState(); | ||||
|     reserve.updateState(cachedData); | ||||
| 
 | ||||
|     IStableDebtToken(address(stableDebtToken)).burn(user, stableDebt); | ||||
|     IStableDebtToken(address(stableDebtToken)).mint( | ||||
|  | @ -435,6 +438,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
|     uint256 currentPremium; | ||||
|     uint256 currentAmountPlusPremium; | ||||
|     address debtToken; | ||||
|     address[] aTokenAddresses; | ||||
|     uint256[] premiums; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -465,40 +470,44 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
|   ) external override whenNotPaused { | ||||
|     FlashLoanLocalVars memory vars; | ||||
| 
 | ||||
|     vars.aTokenAddresses = new address[](assets.length); | ||||
|     vars.premiums = new uint256[](assets.length); | ||||
| 
 | ||||
|     ValidationLogic.validateFlashloan(assets, amounts, _reserves); | ||||
| 
 | ||||
|     address[] memory aTokenAddresses = new address[](assets.length); | ||||
|     uint256[] memory premiums = new uint256[](assets.length); | ||||
| 
 | ||||
|     vars.receiver = IFlashLoanReceiver(receiverAddress); | ||||
| 
 | ||||
|     for (vars.i = 0; vars.i < assets.length; vars.i++) { | ||||
|       aTokenAddresses[vars.i] = _reserves[assets[vars.i]].aTokenAddress; | ||||
|       vars.aTokenAddresses[vars.i] = _reserves[assets[vars.i]].aTokenAddress; | ||||
| 
 | ||||
|       premiums[vars.i] = amounts[vars.i].mul(_flashLoanPremiumTotal).div(10000); | ||||
|       vars.premiums[vars.i] = amounts[vars.i].mul(_flashLoanPremiumTotal).div(10000); | ||||
| 
 | ||||
|       IAToken(aTokenAddresses[vars.i]).transferUnderlyingTo(receiverAddress, amounts[vars.i]); | ||||
|       IAToken(vars.aTokenAddresses[vars.i]).transferUnderlyingTo(receiverAddress, amounts[vars.i]); | ||||
|     } | ||||
| 
 | ||||
|     require( | ||||
|       vars.receiver.executeOperation(assets, amounts, premiums, msg.sender, params), | ||||
|       vars.receiver.executeOperation(assets, amounts, vars.premiums, msg.sender, params), | ||||
|       Errors.LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN | ||||
|     ); | ||||
| 
 | ||||
|     for (vars.i = 0; vars.i < assets.length; vars.i++) { | ||||
|       vars.currentAsset = assets[vars.i]; | ||||
|       vars.currentAmount = amounts[vars.i]; | ||||
|       vars.currentPremium = premiums[vars.i]; | ||||
|       vars.currentATokenAddress = aTokenAddresses[vars.i]; | ||||
|       vars.currentPremium = vars.premiums[vars.i]; | ||||
|       vars.currentATokenAddress = vars.aTokenAddresses[vars.i]; | ||||
|       vars.currentAmountPlusPremium = vars.currentAmount.add(vars.currentPremium); | ||||
| 
 | ||||
|       if (DataTypes.InterestRateMode(modes[vars.i]) == DataTypes.InterestRateMode.NONE) { | ||||
|         _reserves[vars.currentAsset].updateState(); | ||||
|         _reserves[vars.currentAsset].cumulateToLiquidityIndex( | ||||
|         DataTypes.ReserveData storage reserve = _reserves[vars.currentAsset]; | ||||
|         CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve); | ||||
| 
 | ||||
|         reserve.updateState(cachedData); | ||||
|         reserve.cumulateToLiquidityIndex( | ||||
|           IERC20(vars.currentATokenAddress).totalSupply(), | ||||
|           vars.currentPremium | ||||
|         ); | ||||
|         _reserves[vars.currentAsset].updateInterestRates( | ||||
|         reserve.updateInterestRates( | ||||
|           vars.currentAsset, | ||||
|           vars.currentATokenAddress, | ||||
|           vars.currentAmountPlusPremium, | ||||
|  | @ -863,6 +872,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
|   function _executeBorrow(ExecuteBorrowParams memory vars) internal { | ||||
|     DataTypes.ReserveData storage reserve = _reserves[vars.asset]; | ||||
|     DataTypes.UserConfigurationMap storage userConfig = _usersConfig[vars.onBehalfOf]; | ||||
|     CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve); | ||||
| 
 | ||||
|     address oracle = _addressesProvider.getPriceOracle(); | ||||
| 
 | ||||
|  | @ -886,7 +896,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
|       oracle | ||||
|     ); | ||||
| 
 | ||||
|     reserve.updateState(); | ||||
|     reserve.updateState(cachedData); | ||||
| 
 | ||||
|     uint256 currentStableRate = 0; | ||||
| 
 | ||||
|  | @ -944,17 +954,16 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
|     uint16 referralCode | ||||
|   ) internal { | ||||
|     DataTypes.ReserveData storage reserve = _reserves[asset]; | ||||
|     CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve); | ||||
| 
 | ||||
|     ValidationLogic.validateDeposit(reserve, amount); | ||||
| 
 | ||||
|     address aToken = reserve.aTokenAddress; | ||||
|     reserve.updateState(cachedData); | ||||
|     reserve.updateInterestRates(asset, cachedData.aTokenAddress, amount, 0); | ||||
| 
 | ||||
|     reserve.updateState(); | ||||
|     reserve.updateInterestRates(asset, aToken, amount, 0); | ||||
|     IERC20(asset).safeTransferFrom(msg.sender, cachedData.aTokenAddress, amount); | ||||
| 
 | ||||
|     IERC20(asset).safeTransferFrom(msg.sender, aToken, amount); | ||||
| 
 | ||||
|     bool isFirstDeposit = IAToken(aToken).mint(onBehalfOf, amount, reserve.liquidityIndex); | ||||
|     bool isFirstDeposit = IAToken(cachedData.aTokenAddress).mint(onBehalfOf, amount, cachedData.newLiquidityIndex); | ||||
| 
 | ||||
|     if (isFirstDeposit) { | ||||
|       _usersConfig[onBehalfOf].setUsingAsCollateral(reserve.id, true); | ||||
|  | @ -971,14 +980,13 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
|   ) internal returns (uint256) { | ||||
|     DataTypes.ReserveData storage reserve = _reserves[asset]; | ||||
|     DataTypes.UserConfigurationMap storage userConfig = _usersConfig[msg.sender]; | ||||
|     CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve); | ||||
| 
 | ||||
|     address aToken = reserve.aTokenAddress; | ||||
| 
 | ||||
|     reserve.updateState(); | ||||
|     reserve.updateState(cachedData); | ||||
| 
 | ||||
|     uint256 liquidityIndex = reserve.liquidityIndex; | ||||
| 
 | ||||
|     uint256 userBalance = IAToken(aToken).scaledBalanceOf(msg.sender).rayMul(liquidityIndex); | ||||
|     uint256 userBalance = IAToken(aToken).scaledBalanceOf(msg.sender).rayMul(cachedData.newLiquidityIndex); | ||||
| 
 | ||||
|     uint256 amountToWithdraw = amount; | ||||
| 
 | ||||
|  | @ -990,7 +998,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
| 
 | ||||
|     reserve.updateInterestRates(asset, aToken, 0, amountToWithdraw); | ||||
| 
 | ||||
|     IAToken(aToken).burn(msg.sender, to, amountToWithdraw, liquidityIndex); | ||||
|     IAToken(aToken).burn(msg.sender, to, amountToWithdraw, cachedData.newLiquidityIndex); | ||||
| 
 | ||||
|     if (userConfig.isUsingAsCollateral(reserve.id)) { | ||||
|       if (userConfig.isBorrowingAny()) { | ||||
|  | @ -1022,6 +1030,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
|     address onBehalfOf | ||||
|   ) internal returns (uint256) { | ||||
|     DataTypes.ReserveData storage reserve = _reserves[asset]; | ||||
|     CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve); | ||||
| 
 | ||||
|     (uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(onBehalfOf, reserve); | ||||
| 
 | ||||
|  | @ -1043,7 +1052,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage | |||
|       paybackAmount = amount; | ||||
|     } | ||||
| 
 | ||||
|     reserve.updateState(); | ||||
|     reserve.updateState(cachedData); | ||||
| 
 | ||||
|     if (interestRateMode == DataTypes.InterestRateMode.STABLE) { | ||||
|       IStableDebtToken(reserve.stableDebtTokenAddress).burn(onBehalfOf, paybackAmount); | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ import {Errors} from '../libraries/helpers/Errors.sol'; | |||
| import {ValidationLogic} from '../libraries/logic/ValidationLogic.sol'; | ||||
| import {DataTypes} from '../libraries/types/DataTypes.sol'; | ||||
| import {LendingPoolStorage} from './LendingPoolStorage.sol'; | ||||
| import {CachingHelper} from '../libraries/helpers/CachingHelper.sol'; | ||||
| 
 | ||||
| /** | ||||
|  * @title LendingPoolCollateralManager contract | ||||
|  | @ -160,7 +161,9 @@ contract LendingPoolCollateralManager is | |||
|       } | ||||
|     } | ||||
| 
 | ||||
|     debtReserve.updateState(); | ||||
|     CachingHelper.CachedData memory debtReserveCachedData = CachingHelper.fetchData(debtReserve); | ||||
| 
 | ||||
|     debtReserve.updateState(debtReserveCachedData); | ||||
| 
 | ||||
|     if (vars.userVariableDebt >= vars.actualDebtToLiquidate) { | ||||
|       IVariableDebtToken(debtReserve.variableDebtTokenAddress).burn( | ||||
|  | @ -200,7 +203,9 @@ contract LendingPoolCollateralManager is | |||
|         emit ReserveUsedAsCollateralEnabled(collateralAsset, msg.sender); | ||||
|       } | ||||
|     } else { | ||||
|       collateralReserve.updateState(); | ||||
|       CachingHelper.CachedData memory collateralReserveCachedData = CachingHelper.fetchData(collateralReserve); | ||||
| 
 | ||||
|       collateralReserve.updateState(collateralReserveCachedData); | ||||
|       collateralReserve.updateInterestRates( | ||||
|         collateralAsset, | ||||
|         address(vars.collateralAtoken), | ||||
|  |  | |||
							
								
								
									
										59
									
								
								contracts/protocol/libraries/helpers/CachingHelper.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								contracts/protocol/libraries/helpers/CachingHelper.sol
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | |||
| pragma solidity 0.6.12; | ||||
| 
 | ||||
| pragma experimental ABIEncoderV2; | ||||
| 
 | ||||
| import {DataTypes} from '../types/DataTypes.sol'; | ||||
| import {IVariableDebtToken} from '../../../interfaces/IVariableDebtToken.sol'; | ||||
| 
 | ||||
| library CachingHelper { | ||||
|   struct CachedData { | ||||
|     uint256 oldScaledVariableDebt; | ||||
|     uint256 oldTotalVariableDebt; | ||||
|     uint256 newSscaledVariableDebt; | ||||
|     uint256 newTtotalVariableDebt; | ||||
|     uint256 oldPrincipalStableDebt; | ||||
|     uint256 oldAvgStableBorrowRate; | ||||
|     uint256 oldTotalStableDebt; | ||||
|     uint256 newPrincipalStableDebt; | ||||
|     uint256 newAvgStableBorrowRate; | ||||
|     uint256 newTotalStableDebt; | ||||
|     uint256 oldLiquidityIndex; | ||||
|     uint256 newLiquidityIndex; | ||||
|     uint256 oldVariableBorrowIndex; | ||||
|     uint256 newVariableBorrowIndex; | ||||
|     uint256 oldLiquidityRate; | ||||
|     uint256 oldVariableBorrowRate; | ||||
|     DataTypes.ReserveConfigurationMap reserveConfiguration; | ||||
|     address aTokenAddress; | ||||
|     address stableDebtTokenAddress; | ||||
|     address variableDebtTokenAddress; | ||||
|     uint40 reserveLastUpdateTimestamp; | ||||
|   } | ||||
| 
 | ||||
|   function fetchData(DataTypes.ReserveData storage reserveData) | ||||
|     internal | ||||
|     view | ||||
|     returns (CachingHelper.CachedData memory) | ||||
|   { | ||||
|     CachedData memory cachedData; | ||||
| 
 | ||||
|     cachedData.oldLiquidityIndex = reserveData.liquidityIndex; | ||||
|     cachedData.oldVariableBorrowIndex = reserveData.variableBorrowIndex; | ||||
| 
 | ||||
|     cachedData.aTokenAddress = reserveData.aTokenAddress; | ||||
|     cachedData.stableDebtTokenAddress = reserveData.stableDebtTokenAddress; | ||||
|     cachedData.variableDebtTokenAddress = reserveData.variableDebtTokenAddress; | ||||
| 
 | ||||
|     cachedData.reserveConfiguration = reserveData.configuration; | ||||
| 
 | ||||
|     cachedData.oldLiquidityRate = reserveData.currentLiquidityRate; | ||||
|     cachedData.oldVariableBorrowRate = reserveData.currentVariableBorrowRate; | ||||
| 
 | ||||
|     cachedData.reserveLastUpdateTimestamp = reserveData.lastUpdateTimestamp; | ||||
| 
 | ||||
|     cachedData.oldScaledVariableDebt = IVariableDebtToken(cachedData.variableDebtTokenAddress) | ||||
|       .scaledTotalSupply(); | ||||
|      | ||||
|     return cachedData; | ||||
|   } | ||||
| } | ||||
|  | @ -14,6 +14,7 @@ import {WadRayMath} from '../math/WadRayMath.sol'; | |||
| import {PercentageMath} from '../math/PercentageMath.sol'; | ||||
| import {Errors} from '../helpers/Errors.sol'; | ||||
| import {DataTypes} from '../types/DataTypes.sol'; | ||||
| import {CachingHelper} from '../helpers/CachingHelper.sol'; | ||||
| 
 | ||||
| /** | ||||
|  * @title ReserveLogic library | ||||
|  | @ -107,29 +108,22 @@ library ReserveLogic { | |||
|    * @dev Updates the liquidity cumulative index and the variable borrow index. | ||||
|    * @param reserve the reserve object | ||||
|    **/ | ||||
|   function updateState(DataTypes.ReserveData storage reserve) internal { | ||||
|     uint256 scaledVariableDebt = | ||||
|       IVariableDebtToken(reserve.variableDebtTokenAddress).scaledTotalSupply(); | ||||
|     uint256 previousVariableBorrowIndex = reserve.variableBorrowIndex; | ||||
|     uint256 previousLiquidityIndex = reserve.liquidityIndex; | ||||
|     uint40 lastUpdatedTimestamp = reserve.lastUpdateTimestamp; | ||||
|   function updateState(DataTypes.ReserveData storage reserve, CachingHelper.CachedData memory cachedData) internal { | ||||
| 
 | ||||
|     (uint256 newLiquidityIndex, uint256 newVariableBorrowIndex) = | ||||
|       _updateIndexes( | ||||
|         reserve, | ||||
|         scaledVariableDebt, | ||||
|         previousLiquidityIndex, | ||||
|         previousVariableBorrowIndex, | ||||
|         lastUpdatedTimestamp | ||||
|         cachedData | ||||
|       ); | ||||
| 
 | ||||
|      | ||||
| 
 | ||||
|     _accrueToTreasury( | ||||
|       reserve, | ||||
|       scaledVariableDebt, | ||||
|       previousVariableBorrowIndex, | ||||
|       newLiquidityIndex, | ||||
|       newVariableBorrowIndex, | ||||
|       lastUpdatedTimestamp | ||||
|       cachedData.oldScaledVariableDebt, | ||||
|       cachedData.oldVariableBorrowIndex, | ||||
|       cachedData.newLiquidityIndex, | ||||
|       cachedData.newVariableBorrowIndex, | ||||
|       cachedData.reserveLastUpdateTimestamp | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|  | @ -209,9 +203,7 @@ library ReserveLogic { | |||
|     (vars.totalStableDebt, vars.avgStableRate) = IStableDebtToken(vars.stableDebtTokenAddress) | ||||
|       .getTotalSupplyAndAvgRate(); | ||||
| 
 | ||||
|     //calculates the total variable debt locally using the scaled total supply instead | ||||
|     //of totalSupply(), as it's noticeably cheaper. Also, the index has been | ||||
|     //updated by the previous updateState() call | ||||
| 
 | ||||
|     vars.totalVariableDebt = IVariableDebtToken(reserve.variableDebtTokenAddress) | ||||
|       .scaledTotalSupply() | ||||
|       .rayMul(reserve.variableBorrowIndex); | ||||
|  | @ -327,47 +319,40 @@ library ReserveLogic { | |||
|   /** | ||||
|    * @dev Updates the reserve indexes and the timestamp of the update | ||||
|    * @param reserve The reserve reserve to be updated | ||||
|    * @param scaledVariableDebt The scaled variable debt | ||||
|    * @param liquidityIndex The last stored liquidity index | ||||
|    * @param variableBorrowIndex The last stored variable borrow index | ||||
|    * @param cachedData The cache layer holding the cached protocol data | ||||
|    **/ | ||||
|   function _updateIndexes( | ||||
|     DataTypes.ReserveData storage reserve, | ||||
|     uint256 scaledVariableDebt, | ||||
|     uint256 liquidityIndex, | ||||
|     uint256 variableBorrowIndex, | ||||
|     uint40 timestamp | ||||
|   ) internal returns (uint256, uint256) { | ||||
|     uint256 currentLiquidityRate = reserve.currentLiquidityRate; | ||||
|     CachingHelper.CachedData memory cachedData | ||||
|   ) internal { | ||||
| 
 | ||||
|     uint256 newLiquidityIndex = liquidityIndex; | ||||
|     uint256 newVariableBorrowIndex = variableBorrowIndex; | ||||
|     cachedData.newLiquidityIndex = cachedData.oldLiquidityIndex; | ||||
|     cachedData.newVariableBorrowIndex = cachedData.oldVariableBorrowIndex; | ||||
| 
 | ||||
|     //only cumulating if there is any income being produced | ||||
|     if (currentLiquidityRate > 0) { | ||||
|     if (cachedData.oldLiquidityRate > 0) { | ||||
|       uint256 cumulatedLiquidityInterest = | ||||
|         MathUtils.calculateLinearInterest(currentLiquidityRate, timestamp); | ||||
|       newLiquidityIndex = cumulatedLiquidityInterest.rayMul(liquidityIndex); | ||||
|       require(newLiquidityIndex <= type(uint128).max, Errors.RL_LIQUIDITY_INDEX_OVERFLOW); | ||||
|         MathUtils.calculateLinearInterest(cachedData.oldLiquidityRate, cachedData.reserveLastUpdateTimestamp); | ||||
|        cachedData.newLiquidityIndex = cumulatedLiquidityInterest.rayMul(cachedData.oldLiquidityIndex); | ||||
|       require( cachedData.newLiquidityIndex <= type(uint128).max, Errors.RL_LIQUIDITY_INDEX_OVERFLOW); | ||||
| 
 | ||||
|       reserve.liquidityIndex = uint128(newLiquidityIndex); | ||||
|       reserve.liquidityIndex = uint128(cachedData.newLiquidityIndex); | ||||
| 
 | ||||
|       //as the liquidity rate might come only from stable rate loans, we need to ensure | ||||
|       //that there is actual variable debt before accumulating | ||||
|       if (scaledVariableDebt != 0) { | ||||
|       if (cachedData.oldScaledVariableDebt != 0) { | ||||
|         uint256 cumulatedVariableBorrowInterest = | ||||
|           MathUtils.calculateCompoundedInterest(reserve.currentVariableBorrowRate, timestamp); | ||||
|         newVariableBorrowIndex = cumulatedVariableBorrowInterest.rayMul(variableBorrowIndex); | ||||
|           MathUtils.calculateCompoundedInterest(cachedData.oldVariableBorrowRate, cachedData.reserveLastUpdateTimestamp); | ||||
|         cachedData.newVariableBorrowIndex = cumulatedVariableBorrowInterest.rayMul(cachedData.oldVariableBorrowIndex); | ||||
|         require( | ||||
|           newVariableBorrowIndex <= type(uint128).max, | ||||
|           cachedData.newVariableBorrowIndex <= type(uint128).max, | ||||
|           Errors.RL_VARIABLE_BORROW_INDEX_OVERFLOW | ||||
|         ); | ||||
|         reserve.variableBorrowIndex = uint128(newVariableBorrowIndex); | ||||
|         reserve.variableBorrowIndex = uint128(cachedData.newVariableBorrowIndex); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     //solium-disable-next-line | ||||
|     reserve.lastUpdateTimestamp = uint40(block.timestamp); | ||||
|     return (newLiquidityIndex, newVariableBorrowIndex); | ||||
|   } | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 The3D
						The3D