diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 24a9ae4b..f349d412 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -49,6 +49,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage using WadRayMath for uint256; using PercentageMath for uint256; using SafeERC20 for IERC20; + using ReserveLogic for DataTypes.ReserveCache; uint256 public constant LENDINGPOOL_REVISION = 0x2; @@ -288,40 +289,26 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage if (interestRateMode == DataTypes.InterestRateMode.STABLE) { IStableDebtToken(reserveCache.stableDebtTokenAddress).burn(msg.sender, stableDebt); - - reserveCache.nextPrincipalStableDebt = reserveCache.nextTotalStableDebt = reserveCache - .currTotalStableDebt - .sub(stableDebt); - IVariableDebtToken(reserveCache.variableDebtTokenAddress).mint( msg.sender, msg.sender, stableDebt, reserveCache.nextVariableBorrowIndex ); - reserveCache.nextScaledVariableDebt = reserveCache.currScaledVariableDebt.add( - stableDebt.rayDiv(reserveCache.nextVariableBorrowIndex) - ); + reserveCache.refreshDebt(0, stableDebt, stableDebt, 0); } else { IVariableDebtToken(reserveCache.variableDebtTokenAddress).burn( msg.sender, variableDebt, reserveCache.nextVariableBorrowIndex ); - reserveCache.nextScaledVariableDebt = reserveCache.currScaledVariableDebt.sub( - variableDebt.rayDiv(reserveCache.nextVariableBorrowIndex) - ); - IStableDebtToken(reserveCache.stableDebtTokenAddress).mint( msg.sender, msg.sender, variableDebt, reserve.currentStableBorrowRate ); - - reserveCache.nextPrincipalStableDebt = reserveCache.nextTotalStableDebt = reserveCache - .currTotalStableDebt - .add(stableDebt); + reserveCache.refreshDebt(variableDebt, 0, 0, variableDebt); } reserve.updateInterestRates(reserveCache, asset, 0, 0); @@ -365,6 +352,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage reserve.currentStableBorrowRate ); + reserveCache.refreshDebt(stableDebt, stableDebt, 0, 0); + reserve.updateInterestRates(reserveCache, asset, 0, 0); emit RebalanceStableBorrowRate(asset, user); @@ -915,8 +904,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage ); uint256 currentStableRate = 0; - bool isFirstBorrowing = false; + if (DataTypes.InterestRateMode(vars.interestRateMode) == DataTypes.InterestRateMode.STABLE) { currentStableRate = reserve.currentStableBorrowRate; @@ -926,11 +915,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage vars.amount, currentStableRate ); - - reserveCache.nextPrincipalStableDebt = reserveCache.nextTotalStableDebt = reserveCache - .currTotalStableDebt - .add(vars.amount); - + reserveCache.refreshDebt(vars.amount, 0, 0, 0); } else { isFirstBorrowing = IVariableDebtToken(reserveCache.variableDebtTokenAddress).mint( vars.user, @@ -938,10 +923,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage vars.amount, reserveCache.nextVariableBorrowIndex ); - - reserveCache.nextScaledVariableDebt = reserveCache.nextScaledVariableDebt.add( - vars.amount.rayDiv(reserveCache.nextVariableBorrowIndex) - ); + reserveCache.refreshDebt(0, 0, vars.amount, 0); } if (isFirstBorrowing) { @@ -1090,18 +1072,14 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage if (interestRateMode == DataTypes.InterestRateMode.STABLE) { IStableDebtToken(reserveCache.stableDebtTokenAddress).burn(onBehalfOf, paybackAmount); - reserveCache.nextPrincipalStableDebt = reserveCache.nextTotalStableDebt = reserveCache - .currTotalStableDebt - .sub(paybackAmount); + reserveCache.refreshDebt(0, paybackAmount, 0, 0); } else { IVariableDebtToken(reserveCache.variableDebtTokenAddress).burn( onBehalfOf, paybackAmount, reserveCache.nextVariableBorrowIndex ); - reserveCache.nextScaledVariableDebt = reserveCache.currScaledVariableDebt.sub( - paybackAmount.rayDiv(reserveCache.nextVariableBorrowIndex) - ); + reserveCache.refreshDebt(0, 0, 0, paybackAmount); } reserve.updateInterestRates(reserveCache, asset, paybackAmount, 0); diff --git a/contracts/protocol/lendingpool/LendingPoolCollateralManager.sol b/contracts/protocol/lendingpool/LendingPoolCollateralManager.sol index 19908705..b757f9de 100644 --- a/contracts/protocol/lendingpool/LendingPoolCollateralManager.sol +++ b/contracts/protocol/lendingpool/LendingPoolCollateralManager.sol @@ -10,6 +10,7 @@ import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol'; import {ILendingPoolCollateralManager} from '../../interfaces/ILendingPoolCollateralManager.sol'; import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol'; import {GenericLogic} from '../libraries/logic/GenericLogic.sol'; +import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol'; import {Helpers} from '../libraries/helpers/Helpers.sol'; import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {PercentageMath} from '../libraries/math/PercentageMath.sol'; @@ -35,6 +36,7 @@ contract LendingPoolCollateralManager is using SafeMath for uint256; using WadRayMath for uint256; using PercentageMath for uint256; + using ReserveLogic for DataTypes.ReserveCache; uint256 internal constant LIQUIDATION_CLOSE_FACTOR_PERCENT = 5000; @@ -173,9 +175,8 @@ contract LendingPoolCollateralManager is vars.actualDebtToLiquidate, debtReserveCache.nextVariableBorrowIndex ); - debtReserveCache.nextScaledVariableDebt = debtReserveCache.currScaledVariableDebt.sub( - vars.actualDebtToLiquidate.rayDiv(debtReserveCache.nextVariableBorrowIndex) - ); + debtReserveCache.refreshDebt(0, 0, 0, vars.actualDebtToLiquidate); + debtReserve.updateInterestRates(debtReserveCache, debtAsset, vars.actualDebtToLiquidate, 0); } else { // If the user doesn't have variable debt, no need to try to burn variable debt tokens if (vars.userVariableDebt > 0) { @@ -184,27 +185,20 @@ contract LendingPoolCollateralManager is vars.userVariableDebt, debtReserveCache.nextVariableBorrowIndex ); - debtReserveCache.nextScaledVariableDebt = debtReserveCache - .currScaledVariableDebt - .sub(vars.userVariableDebt.rayDiv(debtReserveCache.nextVariableBorrowIndex)); } IStableDebtToken(debtReserveCache.stableDebtTokenAddress).burn( user, vars.actualDebtToLiquidate.sub(vars.userVariableDebt) ); - - debtReserveCache.nextPrincipalStableDebt = debtReserveCache - .nextTotalStableDebt = debtReserveCache.currTotalStableDebt.sub( - vars.actualDebtToLiquidate.sub(vars.userVariableDebt) + debtReserveCache.refreshDebt( + 0, + vars.actualDebtToLiquidate.sub(vars.userVariableDebt), + 0, + vars.userVariableDebt ); - } - debtReserve.updateInterestRates( - debtReserveCache, - debtAsset, - vars.actualDebtToLiquidate, - 0 - ); + debtReserve.updateInterestRates(debtReserveCache, debtAsset, vars.actualDebtToLiquidate, 0); + } if (receiveAToken) { vars.liquidatorPreviousATokenBalance = IERC20(vars.collateralAtoken).balanceOf(msg.sender); @@ -216,7 +210,7 @@ contract LendingPoolCollateralManager is emit ReserveUsedAsCollateralEnabled(collateralAsset, msg.sender); } } else { - collateralReserve.updateState(collateralReserveCache); + collateralReserve.updateState(collateralReserveCache); collateralReserve.updateInterestRates( collateralReserveCache, collateralAsset, diff --git a/contracts/protocol/libraries/logic/ReserveLogic.sol b/contracts/protocol/libraries/logic/ReserveLogic.sol index 1db225ac..305559e2 100644 --- a/contracts/protocol/libraries/logic/ReserveLogic.sol +++ b/contracts/protocol/libraries/logic/ReserveLogic.sol @@ -186,10 +186,6 @@ library ReserveLogic { ) internal { UpdateInterestRatesLocalVars memory vars; - if (reserveCache.currTotalStableDebt != reserveCache.nextTotalStableDebt) { - reserveCache.nextAvgStableBorrowRate = IStableDebtToken(reserveCache.stableDebtTokenAddress) - .getAverageStableRate(); - } reserveCache.nextTotalVariableDebt = reserveCache.nextScaledVariableDebt.rayMul( reserveCache.nextVariableBorrowIndex @@ -228,11 +224,9 @@ library ReserveLogic { } struct MintToTreasuryLocalVars { - uint256 currentStableDebt; - uint256 principalStableDebt; - uint256 previousStableDebt; - uint256 currentVariableDebt; - uint256 previousVariableDebt; + uint256 prevTotalStableDebt; + uint256 prevTotalVariableDebt; + uint256 currTotalVariableDebt; uint256 avgStableRate; uint256 cumulatedStableInterest; uint256 totalDebtAccrued; @@ -260,12 +254,12 @@ library ReserveLogic { } //calculate the last principal variable debt - vars.previousVariableDebt = reserveCache.currScaledVariableDebt.rayMul( + vars.prevTotalVariableDebt = reserveCache.currScaledVariableDebt.rayMul( reserveCache.currVariableBorrowIndex ); //calculate the new total supply after accumulation of the index - vars.currentVariableDebt = reserveCache.currScaledVariableDebt.rayMul( + vars.currTotalVariableDebt = reserveCache.currScaledVariableDebt.rayMul( reserveCache.nextVariableBorrowIndex ); @@ -276,16 +270,16 @@ library ReserveLogic { reserveCache.reserveLastUpdateTimestamp ); - vars.previousStableDebt = reserveCache.currPrincipalStableDebt.rayMul( + vars.prevTotalStableDebt = reserveCache.currPrincipalStableDebt.rayMul( vars.cumulatedStableInterest ); //debt accrued is the sum of the current debt minus the sum of the debt at the last update vars.totalDebtAccrued = vars - .currentVariableDebt + .currTotalVariableDebt .add(reserveCache.currTotalStableDebt) - .sub(vars.previousVariableDebt) - .sub(vars.previousStableDebt); + .sub(vars.prevTotalVariableDebt) + .sub(vars.prevTotalStableDebt); vars.amountToMint = vars.totalDebtAccrued.percentMul(vars.reserveFactor); @@ -385,4 +379,32 @@ library ReserveLogic { return reserveCache; } + + function refreshDebt( + DataTypes.ReserveCache memory cache, + uint256 stableDebtMinted, + uint256 stableDebtBurned, + uint256 variableDebtMinted, + uint256 variableDebtBurned + ) internal { + uint256 scaledVariableDebtMinted = variableDebtMinted.rayDiv(cache.nextVariableBorrowIndex); + uint256 scaledVariableDebtBurned = variableDebtBurned.rayDiv(cache.nextVariableBorrowIndex); + + if (cache.currTotalStableDebt.add(stableDebtMinted) > stableDebtBurned) { + cache.nextPrincipalStableDebt = cache.nextTotalStableDebt = cache + .currTotalStableDebt + .add(stableDebtMinted) + .sub(stableDebtBurned); + if (stableDebtMinted != 0 || stableDebtBurned != 0) { + cache.nextAvgStableBorrowRate = IStableDebtToken(cache.stableDebtTokenAddress) + .getAverageStableRate(); + } + } else { + cache.nextPrincipalStableDebt = cache.nextTotalStableDebt = cache.nextAvgStableBorrowRate = 0; + } + + cache.nextScaledVariableDebt = cache.currScaledVariableDebt.add(scaledVariableDebtMinted).sub( + scaledVariableDebtBurned + ); + } } diff --git a/package-lock.json b/package-lock.json index 7f3c76fd..e5198127 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14793,7 +14793,7 @@ } }, "ethereumjs-abi": { - "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#1a27c59c15ab1e95ee8e5c4ed6ad814c49cc439e", + "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "dev": true, "requires": {