From b0ddb815b82c8887488055dbd84cb803db5a2967 Mon Sep 17 00:00:00 2001 From: andyk Date: Tue, 25 Aug 2020 13:37:38 +0300 Subject: [PATCH] small lending pool gas optimization --- contracts/lendingpool/LendingPool.sol | 42 ++++++++++--------- .../LendingPoolLiquidationManager.sol | 20 ++++++--- contracts/libraries/logic/ReserveLogic.sol | 19 ++++----- 3 files changed, 45 insertions(+), 36 deletions(-) diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index 16b4d398..ec587920 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -92,22 +92,21 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool { ValidationLogic.validateDeposit(reserve, amount); - IAToken aToken = IAToken(reserve.aTokenAddress); - - bool isFirstDeposit = aToken.balanceOf(msg.sender) == 0; + address aToken = reserve.aTokenAddress; reserve.updateCumulativeIndexesAndTimestamp(); - reserve.updateInterestRates(asset, amount, 0); + reserve.updateInterestRates(asset, aToken, amount, 0); + bool isFirstDeposit = IAToken(aToken).balanceOf(msg.sender) == 0; if (isFirstDeposit) { _usersConfig[msg.sender].setUsingAsCollateral(reserve.index, true); } //minting AToken to user 1:1 with the specific exchange rate - aToken.mint(msg.sender, amount); + IAToken(aToken).mint(msg.sender, amount); //transfer to the aToken contract - IERC20(asset).safeTransferFrom(msg.sender, address(aToken), amount); + IERC20(asset).safeTransferFrom(msg.sender, aToken, amount); //solium-disable-next-line emit Deposit(asset, msg.sender, amount, referralCode); @@ -121,9 +120,9 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool { function withdraw(address asset, uint256 amount) external override nonReentrant { ReserveLogic.ReserveData storage reserve = _reserves[asset]; - IAToken aToken = IAToken(reserve.aTokenAddress); + address aToken = reserve.aTokenAddress; - uint256 userBalance = aToken.balanceOf(msg.sender); + uint256 userBalance = IAToken(aToken).balanceOf(msg.sender); uint256 amountToWithdraw = amount; @@ -134,7 +133,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool { ValidationLogic.validateWithdraw( asset, - address(aToken), + aToken, amountToWithdraw, userBalance, _reserves, @@ -145,13 +144,13 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool { reserve.updateCumulativeIndexesAndTimestamp(); - reserve.updateInterestRates(asset, 0, amountToWithdraw); + reserve.updateInterestRates(asset, aToken, 0, amountToWithdraw); if (amountToWithdraw == userBalance) { _usersConfig[msg.sender].setUsingAsCollateral(reserve.index, false); } - aToken.burn(msg.sender, msg.sender, amountToWithdraw); + IAToken(aToken).burn(msg.sender, msg.sender, amountToWithdraw); //solium-disable-next-line emit Withdraw(asset, msg.sender, amount); @@ -202,14 +201,16 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool { IVariableDebtToken(reserve.variableDebtTokenAddress).mint(msg.sender, amount); } - reserve.updateInterestRates(asset, 0, amount); + address aToken = reserve.aTokenAddress; + reserve.updateInterestRates(asset, aToken, 0, amount); - if (!userConfig.isBorrowing(reserve.index)) { - userConfig.setBorrowing(reserve.index, true); + uint256 reserveIndex = reserve.index; + if (!userConfig.isBorrowing(reserveIndex)) { + userConfig.setBorrowing(reserveIndex, true); } //if we reached this point, we can transfer - IAToken(reserve.aTokenAddress).transferUnderlyingTo(msg.sender, amount); + IAToken(aToken).transferUnderlyingTo(msg.sender, amount); emit Borrow( asset, @@ -270,13 +271,14 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool { IVariableDebtToken(reserve.variableDebtTokenAddress).burn(onBehalfOf, paybackAmount); } - reserve.updateInterestRates(asset, paybackAmount, 0); + address aToken = reserve.aTokenAddress; + reserve.updateInterestRates(asset, aToken, paybackAmount, 0); if (stableDebt.add(variableDebt).sub(paybackAmount) == 0) { _usersConfig[onBehalfOf].setBorrowing(reserve.index, false); } - IERC20(asset).safeTransferFrom(msg.sender, reserve.aTokenAddress, paybackAmount); + IERC20(asset).safeTransferFrom(msg.sender, aToken, paybackAmount); emit Repay(asset, onBehalfOf, msg.sender, paybackAmount); } @@ -317,7 +319,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool { ); } - reserve.updateInterestRates(asset, 0, 0); + reserve.updateInterestRates(asset, reserve.aTokenAddress, 0, 0); emit Swap( asset, @@ -367,7 +369,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool { stableDebtToken.burn(user, stableBorrowBalance); stableDebtToken.mint(user, stableBorrowBalance, reserve.currentStableBorrowRate); - reserve.updateInterestRates(asset, 0, 0); + reserve.updateInterestRates(asset, reserve.aTokenAddress, 0, 0); emit RebalanceStableBorrowRate(asset, user); @@ -501,7 +503,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable, ILendingPool { reserve.cumulateToLiquidityIndex(totalLiquidityBefore, amountFee); //refresh interest rates - reserve.updateInterestRates(asset, amountFee, 0); + reserve.updateInterestRates(asset, aTokenAddress, amountFee, 0); //solium-disable-next-line emit FlashLoan(receiverAddress, asset, amount, amountFee); diff --git a/contracts/lendingpool/LendingPoolLiquidationManager.sol b/contracts/lendingpool/LendingPoolLiquidationManager.sol index 84bf0099..a36ed3f3 100644 --- a/contracts/lendingpool/LendingPoolLiquidationManager.sol +++ b/contracts/lendingpool/LendingPoolLiquidationManager.sol @@ -136,7 +136,9 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl ); } - vars.userCollateralBalance = IERC20(collateralReserve.aTokenAddress).balanceOf(user); + vars.collateralAtoken = IAToken(collateralReserve.aTokenAddress); + + vars.userCollateralBalance = vars.collateralAtoken.balanceOf(user); vars.isCollateralEnabled = collateralReserve.configuration.getLiquidationThreshold() > 0 && @@ -192,8 +194,6 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl vars.actualAmountToLiquidate = vars.principalAmountNeeded; } - vars.collateralAtoken = IAToken(collateralReserve.aTokenAddress); - //if liquidator reclaims the underlying asset, we make sure there is enough available collateral in the reserve if (!receiveAToken) { uint256 currentAvailableCollateral = IERC20(collateral).balanceOf( @@ -209,7 +209,12 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl //update the principal reserve principalReserve.updateCumulativeIndexesAndTimestamp(); - principalReserve.updateInterestRates(principal, vars.actualAmountToLiquidate, 0); + principalReserve.updateInterestRates( + principal, + principalReserve.aTokenAddress, + vars.actualAmountToLiquidate, + 0 + ); if (vars.userVariableDebt >= vars.actualAmountToLiquidate) { IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn( @@ -235,7 +240,12 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl //updating collateral reserve collateralReserve.updateCumulativeIndexesAndTimestamp(); - collateralReserve.updateInterestRates(collateral, 0, vars.maxCollateralToLiquidate); + collateralReserve.updateInterestRates( + collateral, + address(vars.collateralAtoken), + 0, + vars.maxCollateralToLiquidate + ); //burn the equivalent amount of atoken vars.collateralAtoken.burn(user, msg.sender, vars.maxCollateralToLiquidate); diff --git a/contracts/libraries/logic/ReserveLogic.sol b/contracts/libraries/logic/ReserveLogic.sol index 6aab6932..893ca5c5 100644 --- a/contracts/libraries/logic/ReserveLogic.sol +++ b/contracts/libraries/logic/ReserveLogic.sol @@ -126,18 +126,18 @@ library ReserveLogic { IERC20(reserve.variableDebtTokenAddress).totalSupply() > 0 || IERC20(reserve.stableDebtTokenAddress).totalSupply() > 0 ) { + uint40 lastUpdateTimestamp = reserve.lastUpdateTimestamp; + uint256 cumulatedLiquidityInterest = MathUtils.calculateLinearInterest( reserve.currentLiquidityRate, - reserve.lastUpdateTimestamp + lastUpdateTimestamp ); - reserve.lastLiquidityIndex = cumulatedLiquidityInterest.rayMul( - reserve.lastLiquidityIndex - ); + reserve.lastLiquidityIndex = cumulatedLiquidityInterest.rayMul(reserve.lastLiquidityIndex); uint256 cumulatedVariableBorrowInterest = MathUtils.calculateCompoundedInterest( reserve.currentVariableBorrowRate, - reserve.lastUpdateTimestamp + lastUpdateTimestamp ); reserve.lastVariableBorrowIndex = cumulatedVariableBorrowInterest.rayMul( reserve.lastVariableBorrowIndex @@ -164,9 +164,7 @@ library ReserveLogic { uint256 cumulatedLiquidity = amountToLiquidityRatio.add(WadRayMath.ray()); - reserve.lastLiquidityIndex = cumulatedLiquidity.rayMul( - reserve.lastLiquidityIndex - ); + reserve.lastLiquidityIndex = cumulatedLiquidity.rayMul(reserve.lastLiquidityIndex); } /** @@ -208,21 +206,20 @@ library ReserveLogic { function updateInterestRates( ReserveData storage reserve, address reserveAddress, + address aTokenAddress, uint256 liquidityAdded, uint256 liquidityTaken ) internal { uint256 currentAvgStableRate = IStableDebtToken(reserve.stableDebtTokenAddress) .getAverageStableRate(); - uint256 balance = IERC20(reserveAddress).balanceOf(reserve.aTokenAddress); - ( uint256 newLiquidityRate, uint256 newStableRate, uint256 newVariableRate ) = IReserveInterestRateStrategy(reserve.interestRateStrategyAddress).calculateInterestRates( reserveAddress, - balance.add(liquidityAdded).sub(liquidityTaken), + IERC20(reserveAddress).balanceOf(aTokenAddress).add(liquidityAdded).sub(liquidityTaken), IERC20(reserve.stableDebtTokenAddress).totalSupply(), IERC20(reserve.variableDebtTokenAddress).totalSupply(), currentAvgStableRate