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 {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
|
||||||
import {DataTypes} from '../libraries/types/DataTypes.sol';
|
import {DataTypes} from '../libraries/types/DataTypes.sol';
|
||||||
import {LendingPoolStorage} from './LendingPoolStorage.sol';
|
import {LendingPoolStorage} from './LendingPoolStorage.sol';
|
||||||
|
import {CachingHelper} from '../libraries/helpers/CachingHelper.sol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title LendingPool contract
|
* @title LendingPool contract
|
||||||
|
@ -270,6 +271,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
**/
|
**/
|
||||||
function swapBorrowRateMode(address asset, uint256 rateMode) external override whenNotPaused {
|
function swapBorrowRateMode(address asset, uint256 rateMode) external override whenNotPaused {
|
||||||
DataTypes.ReserveData storage reserve = _reserves[asset];
|
DataTypes.ReserveData storage reserve = _reserves[asset];
|
||||||
|
CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve);
|
||||||
|
|
||||||
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve);
|
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve);
|
||||||
|
|
||||||
|
@ -283,7 +285,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
interestRateMode
|
interestRateMode
|
||||||
);
|
);
|
||||||
|
|
||||||
reserve.updateState();
|
reserve.updateState(cachedData);
|
||||||
|
|
||||||
if (interestRateMode == DataTypes.InterestRateMode.STABLE) {
|
if (interestRateMode == DataTypes.InterestRateMode.STABLE) {
|
||||||
IStableDebtToken(reserve.stableDebtTokenAddress).burn(msg.sender, stableDebt);
|
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 {
|
function rebalanceStableBorrowRate(address asset, address user) external override whenNotPaused {
|
||||||
DataTypes.ReserveData storage reserve = _reserves[asset];
|
DataTypes.ReserveData storage reserve = _reserves[asset];
|
||||||
|
CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve);
|
||||||
|
|
||||||
IERC20 stableDebtToken = IERC20(reserve.stableDebtTokenAddress);
|
IERC20 stableDebtToken = IERC20(reserve.stableDebtTokenAddress);
|
||||||
IERC20 variableDebtToken = IERC20(reserve.variableDebtTokenAddress);
|
IERC20 variableDebtToken = IERC20(reserve.variableDebtTokenAddress);
|
||||||
|
@ -338,7 +341,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
aTokenAddress
|
aTokenAddress
|
||||||
);
|
);
|
||||||
|
|
||||||
reserve.updateState();
|
reserve.updateState(cachedData);
|
||||||
|
|
||||||
IStableDebtToken(address(stableDebtToken)).burn(user, stableDebt);
|
IStableDebtToken(address(stableDebtToken)).burn(user, stableDebt);
|
||||||
IStableDebtToken(address(stableDebtToken)).mint(
|
IStableDebtToken(address(stableDebtToken)).mint(
|
||||||
|
@ -435,6 +438,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
uint256 currentPremium;
|
uint256 currentPremium;
|
||||||
uint256 currentAmountPlusPremium;
|
uint256 currentAmountPlusPremium;
|
||||||
address debtToken;
|
address debtToken;
|
||||||
|
address[] aTokenAddresses;
|
||||||
|
uint256[] premiums;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -465,40 +470,44 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
) external override whenNotPaused {
|
) external override whenNotPaused {
|
||||||
FlashLoanLocalVars memory vars;
|
FlashLoanLocalVars memory vars;
|
||||||
|
|
||||||
|
vars.aTokenAddresses = new address[](assets.length);
|
||||||
|
vars.premiums = new uint256[](assets.length);
|
||||||
|
|
||||||
ValidationLogic.validateFlashloan(assets, amounts, _reserves);
|
ValidationLogic.validateFlashloan(assets, amounts, _reserves);
|
||||||
|
|
||||||
address[] memory aTokenAddresses = new address[](assets.length);
|
|
||||||
uint256[] memory premiums = new uint256[](assets.length);
|
|
||||||
|
|
||||||
vars.receiver = IFlashLoanReceiver(receiverAddress);
|
vars.receiver = IFlashLoanReceiver(receiverAddress);
|
||||||
|
|
||||||
for (vars.i = 0; vars.i < assets.length; vars.i++) {
|
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(
|
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
|
Errors.LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN
|
||||||
);
|
);
|
||||||
|
|
||||||
for (vars.i = 0; vars.i < assets.length; vars.i++) {
|
for (vars.i = 0; vars.i < assets.length; vars.i++) {
|
||||||
vars.currentAsset = assets[vars.i];
|
vars.currentAsset = assets[vars.i];
|
||||||
vars.currentAmount = amounts[vars.i];
|
vars.currentAmount = amounts[vars.i];
|
||||||
vars.currentPremium = premiums[vars.i];
|
vars.currentPremium = vars.premiums[vars.i];
|
||||||
vars.currentATokenAddress = aTokenAddresses[vars.i];
|
vars.currentATokenAddress = vars.aTokenAddresses[vars.i];
|
||||||
vars.currentAmountPlusPremium = vars.currentAmount.add(vars.currentPremium);
|
vars.currentAmountPlusPremium = vars.currentAmount.add(vars.currentPremium);
|
||||||
|
|
||||||
if (DataTypes.InterestRateMode(modes[vars.i]) == DataTypes.InterestRateMode.NONE) {
|
if (DataTypes.InterestRateMode(modes[vars.i]) == DataTypes.InterestRateMode.NONE) {
|
||||||
_reserves[vars.currentAsset].updateState();
|
DataTypes.ReserveData storage reserve = _reserves[vars.currentAsset];
|
||||||
_reserves[vars.currentAsset].cumulateToLiquidityIndex(
|
CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve);
|
||||||
|
|
||||||
|
reserve.updateState(cachedData);
|
||||||
|
reserve.cumulateToLiquidityIndex(
|
||||||
IERC20(vars.currentATokenAddress).totalSupply(),
|
IERC20(vars.currentATokenAddress).totalSupply(),
|
||||||
vars.currentPremium
|
vars.currentPremium
|
||||||
);
|
);
|
||||||
_reserves[vars.currentAsset].updateInterestRates(
|
reserve.updateInterestRates(
|
||||||
vars.currentAsset,
|
vars.currentAsset,
|
||||||
vars.currentATokenAddress,
|
vars.currentATokenAddress,
|
||||||
vars.currentAmountPlusPremium,
|
vars.currentAmountPlusPremium,
|
||||||
|
@ -863,6 +872,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
function _executeBorrow(ExecuteBorrowParams memory vars) internal {
|
function _executeBorrow(ExecuteBorrowParams memory vars) internal {
|
||||||
DataTypes.ReserveData storage reserve = _reserves[vars.asset];
|
DataTypes.ReserveData storage reserve = _reserves[vars.asset];
|
||||||
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[vars.onBehalfOf];
|
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[vars.onBehalfOf];
|
||||||
|
CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve);
|
||||||
|
|
||||||
address oracle = _addressesProvider.getPriceOracle();
|
address oracle = _addressesProvider.getPriceOracle();
|
||||||
|
|
||||||
|
@ -886,7 +896,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
oracle
|
oracle
|
||||||
);
|
);
|
||||||
|
|
||||||
reserve.updateState();
|
reserve.updateState(cachedData);
|
||||||
|
|
||||||
uint256 currentStableRate = 0;
|
uint256 currentStableRate = 0;
|
||||||
|
|
||||||
|
@ -944,17 +954,16 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
uint16 referralCode
|
uint16 referralCode
|
||||||
) internal {
|
) internal {
|
||||||
DataTypes.ReserveData storage reserve = _reserves[asset];
|
DataTypes.ReserveData storage reserve = _reserves[asset];
|
||||||
|
CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve);
|
||||||
|
|
||||||
ValidationLogic.validateDeposit(reserve, amount);
|
ValidationLogic.validateDeposit(reserve, amount);
|
||||||
|
|
||||||
address aToken = reserve.aTokenAddress;
|
reserve.updateState(cachedData);
|
||||||
|
reserve.updateInterestRates(asset, cachedData.aTokenAddress, amount, 0);
|
||||||
|
|
||||||
reserve.updateState();
|
IERC20(asset).safeTransferFrom(msg.sender, cachedData.aTokenAddress, amount);
|
||||||
reserve.updateInterestRates(asset, aToken, amount, 0);
|
|
||||||
|
|
||||||
IERC20(asset).safeTransferFrom(msg.sender, aToken, amount);
|
bool isFirstDeposit = IAToken(cachedData.aTokenAddress).mint(onBehalfOf, amount, cachedData.newLiquidityIndex);
|
||||||
|
|
||||||
bool isFirstDeposit = IAToken(aToken).mint(onBehalfOf, amount, reserve.liquidityIndex);
|
|
||||||
|
|
||||||
if (isFirstDeposit) {
|
if (isFirstDeposit) {
|
||||||
_usersConfig[onBehalfOf].setUsingAsCollateral(reserve.id, true);
|
_usersConfig[onBehalfOf].setUsingAsCollateral(reserve.id, true);
|
||||||
|
@ -971,14 +980,13 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
) internal returns (uint256) {
|
) internal returns (uint256) {
|
||||||
DataTypes.ReserveData storage reserve = _reserves[asset];
|
DataTypes.ReserveData storage reserve = _reserves[asset];
|
||||||
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[msg.sender];
|
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[msg.sender];
|
||||||
|
CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve);
|
||||||
|
|
||||||
address aToken = reserve.aTokenAddress;
|
address aToken = reserve.aTokenAddress;
|
||||||
|
|
||||||
reserve.updateState();
|
reserve.updateState(cachedData);
|
||||||
|
|
||||||
uint256 liquidityIndex = reserve.liquidityIndex;
|
uint256 userBalance = IAToken(aToken).scaledBalanceOf(msg.sender).rayMul(cachedData.newLiquidityIndex);
|
||||||
|
|
||||||
uint256 userBalance = IAToken(aToken).scaledBalanceOf(msg.sender).rayMul(liquidityIndex);
|
|
||||||
|
|
||||||
uint256 amountToWithdraw = amount;
|
uint256 amountToWithdraw = amount;
|
||||||
|
|
||||||
|
@ -990,7 +998,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
|
|
||||||
reserve.updateInterestRates(asset, aToken, 0, amountToWithdraw);
|
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.isUsingAsCollateral(reserve.id)) {
|
||||||
if (userConfig.isBorrowingAny()) {
|
if (userConfig.isBorrowingAny()) {
|
||||||
|
@ -1022,6 +1030,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
address onBehalfOf
|
address onBehalfOf
|
||||||
) internal returns (uint256) {
|
) internal returns (uint256) {
|
||||||
DataTypes.ReserveData storage reserve = _reserves[asset];
|
DataTypes.ReserveData storage reserve = _reserves[asset];
|
||||||
|
CachingHelper.CachedData memory cachedData = CachingHelper.fetchData(reserve);
|
||||||
|
|
||||||
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(onBehalfOf, reserve);
|
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(onBehalfOf, reserve);
|
||||||
|
|
||||||
|
@ -1043,7 +1052,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
paybackAmount = amount;
|
paybackAmount = amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
reserve.updateState();
|
reserve.updateState(cachedData);
|
||||||
|
|
||||||
if (interestRateMode == DataTypes.InterestRateMode.STABLE) {
|
if (interestRateMode == DataTypes.InterestRateMode.STABLE) {
|
||||||
IStableDebtToken(reserve.stableDebtTokenAddress).burn(onBehalfOf, paybackAmount);
|
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 {ValidationLogic} from '../libraries/logic/ValidationLogic.sol';
|
||||||
import {DataTypes} from '../libraries/types/DataTypes.sol';
|
import {DataTypes} from '../libraries/types/DataTypes.sol';
|
||||||
import {LendingPoolStorage} from './LendingPoolStorage.sol';
|
import {LendingPoolStorage} from './LendingPoolStorage.sol';
|
||||||
|
import {CachingHelper} from '../libraries/helpers/CachingHelper.sol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title LendingPoolCollateralManager contract
|
* @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) {
|
if (vars.userVariableDebt >= vars.actualDebtToLiquidate) {
|
||||||
IVariableDebtToken(debtReserve.variableDebtTokenAddress).burn(
|
IVariableDebtToken(debtReserve.variableDebtTokenAddress).burn(
|
||||||
|
@ -200,7 +203,9 @@ contract LendingPoolCollateralManager is
|
||||||
emit ReserveUsedAsCollateralEnabled(collateralAsset, msg.sender);
|
emit ReserveUsedAsCollateralEnabled(collateralAsset, msg.sender);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
collateralReserve.updateState();
|
CachingHelper.CachedData memory collateralReserveCachedData = CachingHelper.fetchData(collateralReserve);
|
||||||
|
|
||||||
|
collateralReserve.updateState(collateralReserveCachedData);
|
||||||
collateralReserve.updateInterestRates(
|
collateralReserve.updateInterestRates(
|
||||||
collateralAsset,
|
collateralAsset,
|
||||||
address(vars.collateralAtoken),
|
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 {PercentageMath} from '../math/PercentageMath.sol';
|
||||||
import {Errors} from '../helpers/Errors.sol';
|
import {Errors} from '../helpers/Errors.sol';
|
||||||
import {DataTypes} from '../types/DataTypes.sol';
|
import {DataTypes} from '../types/DataTypes.sol';
|
||||||
|
import {CachingHelper} from '../helpers/CachingHelper.sol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title ReserveLogic library
|
* @title ReserveLogic library
|
||||||
|
@ -107,29 +108,22 @@ library ReserveLogic {
|
||||||
* @dev Updates the liquidity cumulative index and the variable borrow index.
|
* @dev Updates the liquidity cumulative index and the variable borrow index.
|
||||||
* @param reserve the reserve object
|
* @param reserve the reserve object
|
||||||
**/
|
**/
|
||||||
function updateState(DataTypes.ReserveData storage reserve) internal {
|
function updateState(DataTypes.ReserveData storage reserve, CachingHelper.CachedData memory cachedData) internal {
|
||||||
uint256 scaledVariableDebt =
|
|
||||||
IVariableDebtToken(reserve.variableDebtTokenAddress).scaledTotalSupply();
|
|
||||||
uint256 previousVariableBorrowIndex = reserve.variableBorrowIndex;
|
|
||||||
uint256 previousLiquidityIndex = reserve.liquidityIndex;
|
|
||||||
uint40 lastUpdatedTimestamp = reserve.lastUpdateTimestamp;
|
|
||||||
|
|
||||||
(uint256 newLiquidityIndex, uint256 newVariableBorrowIndex) =
|
|
||||||
_updateIndexes(
|
_updateIndexes(
|
||||||
reserve,
|
reserve,
|
||||||
scaledVariableDebt,
|
cachedData
|
||||||
previousLiquidityIndex,
|
|
||||||
previousVariableBorrowIndex,
|
|
||||||
lastUpdatedTimestamp
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_accrueToTreasury(
|
_accrueToTreasury(
|
||||||
reserve,
|
reserve,
|
||||||
scaledVariableDebt,
|
cachedData.oldScaledVariableDebt,
|
||||||
previousVariableBorrowIndex,
|
cachedData.oldVariableBorrowIndex,
|
||||||
newLiquidityIndex,
|
cachedData.newLiquidityIndex,
|
||||||
newVariableBorrowIndex,
|
cachedData.newVariableBorrowIndex,
|
||||||
lastUpdatedTimestamp
|
cachedData.reserveLastUpdateTimestamp
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,9 +203,7 @@ library ReserveLogic {
|
||||||
(vars.totalStableDebt, vars.avgStableRate) = IStableDebtToken(vars.stableDebtTokenAddress)
|
(vars.totalStableDebt, vars.avgStableRate) = IStableDebtToken(vars.stableDebtTokenAddress)
|
||||||
.getTotalSupplyAndAvgRate();
|
.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)
|
vars.totalVariableDebt = IVariableDebtToken(reserve.variableDebtTokenAddress)
|
||||||
.scaledTotalSupply()
|
.scaledTotalSupply()
|
||||||
.rayMul(reserve.variableBorrowIndex);
|
.rayMul(reserve.variableBorrowIndex);
|
||||||
|
@ -327,47 +319,40 @@ library ReserveLogic {
|
||||||
/**
|
/**
|
||||||
* @dev Updates the reserve indexes and the timestamp of the update
|
* @dev Updates the reserve indexes and the timestamp of the update
|
||||||
* @param reserve The reserve reserve to be updated
|
* @param reserve The reserve reserve to be updated
|
||||||
* @param scaledVariableDebt The scaled variable debt
|
* @param cachedData The cache layer holding the cached protocol data
|
||||||
* @param liquidityIndex The last stored liquidity index
|
|
||||||
* @param variableBorrowIndex The last stored variable borrow index
|
|
||||||
**/
|
**/
|
||||||
function _updateIndexes(
|
function _updateIndexes(
|
||||||
DataTypes.ReserveData storage reserve,
|
DataTypes.ReserveData storage reserve,
|
||||||
uint256 scaledVariableDebt,
|
CachingHelper.CachedData memory cachedData
|
||||||
uint256 liquidityIndex,
|
) internal {
|
||||||
uint256 variableBorrowIndex,
|
|
||||||
uint40 timestamp
|
|
||||||
) internal returns (uint256, uint256) {
|
|
||||||
uint256 currentLiquidityRate = reserve.currentLiquidityRate;
|
|
||||||
|
|
||||||
uint256 newLiquidityIndex = liquidityIndex;
|
cachedData.newLiquidityIndex = cachedData.oldLiquidityIndex;
|
||||||
uint256 newVariableBorrowIndex = variableBorrowIndex;
|
cachedData.newVariableBorrowIndex = cachedData.oldVariableBorrowIndex;
|
||||||
|
|
||||||
//only cumulating if there is any income being produced
|
//only cumulating if there is any income being produced
|
||||||
if (currentLiquidityRate > 0) {
|
if (cachedData.oldLiquidityRate > 0) {
|
||||||
uint256 cumulatedLiquidityInterest =
|
uint256 cumulatedLiquidityInterest =
|
||||||
MathUtils.calculateLinearInterest(currentLiquidityRate, timestamp);
|
MathUtils.calculateLinearInterest(cachedData.oldLiquidityRate, cachedData.reserveLastUpdateTimestamp);
|
||||||
newLiquidityIndex = cumulatedLiquidityInterest.rayMul(liquidityIndex);
|
cachedData.newLiquidityIndex = cumulatedLiquidityInterest.rayMul(cachedData.oldLiquidityIndex);
|
||||||
require(newLiquidityIndex <= type(uint128).max, Errors.RL_LIQUIDITY_INDEX_OVERFLOW);
|
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
|
//as the liquidity rate might come only from stable rate loans, we need to ensure
|
||||||
//that there is actual variable debt before accumulating
|
//that there is actual variable debt before accumulating
|
||||||
if (scaledVariableDebt != 0) {
|
if (cachedData.oldScaledVariableDebt != 0) {
|
||||||
uint256 cumulatedVariableBorrowInterest =
|
uint256 cumulatedVariableBorrowInterest =
|
||||||
MathUtils.calculateCompoundedInterest(reserve.currentVariableBorrowRate, timestamp);
|
MathUtils.calculateCompoundedInterest(cachedData.oldVariableBorrowRate, cachedData.reserveLastUpdateTimestamp);
|
||||||
newVariableBorrowIndex = cumulatedVariableBorrowInterest.rayMul(variableBorrowIndex);
|
cachedData.newVariableBorrowIndex = cumulatedVariableBorrowInterest.rayMul(cachedData.oldVariableBorrowIndex);
|
||||||
require(
|
require(
|
||||||
newVariableBorrowIndex <= type(uint128).max,
|
cachedData.newVariableBorrowIndex <= type(uint128).max,
|
||||||
Errors.RL_VARIABLE_BORROW_INDEX_OVERFLOW
|
Errors.RL_VARIABLE_BORROW_INDEX_OVERFLOW
|
||||||
);
|
);
|
||||||
reserve.variableBorrowIndex = uint128(newVariableBorrowIndex);
|
reserve.variableBorrowIndex = uint128(cachedData.newVariableBorrowIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//solium-disable-next-line
|
//solium-disable-next-line
|
||||||
reserve.lastUpdateTimestamp = uint40(block.timestamp);
|
reserve.lastUpdateTimestamp = uint40(block.timestamp);
|
||||||
return (newLiquidityIndex, newVariableBorrowIndex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user