refactor: further refactored cache, changed linkage behavior of GenericLogic

This commit is contained in:
emilio 2021-06-11 11:27:19 +02:00
parent 666c6a0666
commit 760be1cb42
7 changed files with 145 additions and 110 deletions

View File

@ -20,8 +20,8 @@ import {Errors} from '../libraries/helpers/Errors.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {PercentageMath} from '../libraries/math/PercentageMath.sol'; import {PercentageMath} from '../libraries/math/PercentageMath.sol';
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol'; import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
import {GenericLogic} from '../libraries/logic/GenericLogic.sol';
import {ValidationLogic} from '../libraries/logic/ValidationLogic.sol'; import {ValidationLogic} from '../libraries/logic/ValidationLogic.sol';
import {GenericLogic} from '../libraries/logic/GenericLogic.sol';
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol'; import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
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';
@ -190,7 +190,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
uint16 referralCode, uint16 referralCode,
address onBehalfOf address onBehalfOf
) external override whenNotPaused { ) external override whenNotPaused {
DataTypes.ReserveData storage reserve = _reserves[asset];
_executeBorrow( _executeBorrow(
ExecuteBorrowParams( ExecuteBorrowParams(
asset, asset,
@ -372,7 +371,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
DataTypes.ReserveData storage reserve = _reserves[asset]; DataTypes.ReserveData storage reserve = _reserves[asset];
DataTypes.ReserveCache memory reserveCache = reserve.cache(); DataTypes.ReserveCache memory reserveCache = reserve.cache();
ValidationLogic.validateSetUseReserveAsCollateral(reserve, reserveCache); ValidationLogic.validateSetUseReserveAsCollateral(reserveCache);
_usersConfig[msg.sender].setUsingAsCollateral(reserve.id, useAsCollateral); _usersConfig[msg.sender].setUsingAsCollateral(reserve.id, useAsCollateral);
@ -619,7 +618,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
ltv, ltv,
currentLiquidationThreshold, currentLiquidationThreshold,
healthFactor healthFactor
) = GenericLogic.calculateUserAccountData( ) = GenericLogic.getUserAccountData(
user, user,
_reserves, _reserves,
_usersConfig[user], _usersConfig[user],
@ -990,7 +989,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
reserve.updateState(reserveCache); reserve.updateState(reserveCache);
ValidationLogic.validateDeposit(reserve, reserveCache, amount); ValidationLogic.validateDeposit(reserveCache, amount);
reserve.updateInterestRates(reserveCache, asset, amount, 0); reserve.updateInterestRates(reserveCache, asset, amount, 0);
@ -1029,7 +1028,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
amountToWithdraw = userBalance; amountToWithdraw = userBalance;
} }
ValidationLogic.validateWithdraw(reserve, reserveCache, amountToWithdraw, userBalance); ValidationLogic.validateWithdraw(reserveCache, amountToWithdraw, userBalance);
reserve.updateInterestRates(reserveCache, asset, 0, amountToWithdraw); reserve.updateInterestRates(reserveCache, asset, 0, amountToWithdraw);
@ -1077,7 +1076,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
DataTypes.InterestRateMode interestRateMode = DataTypes.InterestRateMode(rateMode); DataTypes.InterestRateMode interestRateMode = DataTypes.InterestRateMode(rateMode);
ValidationLogic.validateRepay( ValidationLogic.validateRepay(
reserve,
reserveCache, reserveCache,
amount, amount,
interestRateMode, interestRateMode,

View File

@ -1,6 +1,8 @@
// SPDX-License-Identifier: agpl-3.0 // SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12; pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {SafeMath} from '../../dependencies/openzeppelin/contracts//SafeMath.sol'; import {SafeMath} from '../../dependencies/openzeppelin/contracts//SafeMath.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts//IERC20.sol'; import {IERC20} from '../../dependencies/openzeppelin/contracts//IERC20.sol';
import {IAToken} from '../../interfaces/IAToken.sol'; import {IAToken} from '../../interfaces/IAToken.sol';
@ -9,7 +11,6 @@ import {IVariableDebtToken} from '../../interfaces/IVariableDebtToken.sol';
import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol'; import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol';
import {ILendingPoolCollateralManager} from '../../interfaces/ILendingPoolCollateralManager.sol'; import {ILendingPoolCollateralManager} from '../../interfaces/ILendingPoolCollateralManager.sol';
import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol'; import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol';
import {GenericLogic} from '../libraries/logic/GenericLogic.sol';
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol'; import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
import {Helpers} from '../libraries/helpers/Helpers.sol'; import {Helpers} from '../libraries/helpers/Helpers.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {WadRayMath} from '../libraries/math/WadRayMath.sol';
@ -54,6 +55,7 @@ contract LendingPoolCollateralManager is
uint256 healthFactor; uint256 healthFactor;
uint256 liquidatorPreviousATokenBalance; uint256 liquidatorPreviousATokenBalance;
IAToken collateralAtoken; IAToken collateralAtoken;
IPriceOracleGetter oracle;
bool isCollateralEnabled; bool isCollateralEnabled;
DataTypes.InterestRateMode borrowRateMode; DataTypes.InterestRateMode borrowRateMode;
uint256 errorCode; uint256 errorCode;
@ -89,33 +91,25 @@ contract LendingPoolCollateralManager is
) external override returns (uint256, string memory) { ) external override returns (uint256, string memory) {
DataTypes.ReserveData storage collateralReserve = _reserves[collateralAsset]; DataTypes.ReserveData storage collateralReserve = _reserves[collateralAsset];
DataTypes.ReserveData storage debtReserve = _reserves[debtAsset]; DataTypes.ReserveData storage debtReserve = _reserves[debtAsset];
DataTypes.ReserveCache memory debtReserveCache = debtReserve.cache();
DataTypes.UserConfigurationMap storage userConfig = _usersConfig[user]; DataTypes.UserConfigurationMap storage userConfig = _usersConfig[user];
LiquidationCallLocalVars memory vars; LiquidationCallLocalVars memory vars;
(, , , , vars.healthFactor) = GenericLogic.calculateUserAccountData(
(vars.userStableDebt, vars.userVariableDebt) = Helpers.getUserCurrentDebt(user, debtReserve);
vars.oracle = IPriceOracleGetter(_addressesProvider.getPriceOracle());
(vars.errorCode, vars.errorMsg) = ValidationLogic.validateLiquidationCall(
collateralReserve,
debtReserveCache,
vars.userStableDebt.add(vars.userVariableDebt),
user, user,
_reserves, _reserves,
userConfig, userConfig,
_reservesList, _reservesList,
_reservesCount, _reservesCount,
_addressesProvider.getPriceOracle() address(vars.oracle)
);
DataTypes.ReserveCache memory debtReserveCache = debtReserve.cache();
DataTypes.ReserveCache memory collateralReserveCache = collateralReserve.cache();
(vars.userStableDebt, vars.userVariableDebt) = Helpers.getUserCurrentDebt(user, debtReserve);
(vars.errorCode, vars.errorMsg) = ValidationLogic.validateLiquidationCall(
collateralReserve,
debtReserve,
debtReserveCache,
collateralReserveCache,
userConfig,
vars.healthFactor,
vars.userStableDebt,
vars.userVariableDebt
); );
if (Errors.CollateralManagerErrors(vars.errorCode) != Errors.CollateralManagerErrors.NO_ERROR) { if (Errors.CollateralManagerErrors(vars.errorCode) != Errors.CollateralManagerErrors.NO_ERROR) {
@ -139,11 +133,12 @@ contract LendingPoolCollateralManager is
vars.debtAmountNeeded vars.debtAmountNeeded
) = _calculateAvailableCollateralToLiquidate( ) = _calculateAvailableCollateralToLiquidate(
collateralReserve, collateralReserve,
debtReserve, debtReserveCache,
collateralAsset, collateralAsset,
debtAsset, debtAsset,
vars.actualDebtToLiquidate, vars.actualDebtToLiquidate,
vars.userCollateralBalance vars.userCollateralBalance,
vars.oracle
); );
// If debtAmountNeeded < actualDebtToLiquidate, there isn't enough // If debtAmountNeeded < actualDebtToLiquidate, there isn't enough
@ -210,6 +205,7 @@ contract LendingPoolCollateralManager is
emit ReserveUsedAsCollateralEnabled(collateralAsset, msg.sender); emit ReserveUsedAsCollateralEnabled(collateralAsset, msg.sender);
} }
} else { } else {
DataTypes.ReserveCache memory collateralReserveCache = collateralReserve.cache();
collateralReserve.updateState(collateralReserveCache); collateralReserve.updateState(collateralReserveCache);
collateralReserve.updateInterestRates( collateralReserve.updateInterestRates(
collateralReserveCache, collateralReserveCache,
@ -223,7 +219,7 @@ contract LendingPoolCollateralManager is
user, user,
msg.sender, msg.sender,
vars.maxCollateralToLiquidate, vars.maxCollateralToLiquidate,
collateralReserve.liquidityIndex collateralReserveCache.nextLiquidityIndex
); );
} }
@ -237,7 +233,7 @@ contract LendingPoolCollateralManager is
// Transfers the debt asset being repaid to the aToken, where the liquidity is kept // Transfers the debt asset being repaid to the aToken, where the liquidity is kept
IERC20(debtAsset).safeTransferFrom( IERC20(debtAsset).safeTransferFrom(
msg.sender, msg.sender,
debtReserve.aTokenAddress, debtReserveCache.aTokenAddress,
vars.actualDebtToLiquidate vars.actualDebtToLiquidate
); );
@ -270,7 +266,7 @@ contract LendingPoolCollateralManager is
* - This function needs to be called after all the checks to validate the liquidation have been performed, * - This function needs to be called after all the checks to validate the liquidation have been performed,
* otherwise it might fail. * otherwise it might fail.
* @param collateralReserve The data of the collateral reserve * @param collateralReserve The data of the collateral reserve
* @param debtReserve The data of the debt reserve * @param debtReserveCache The cached data of the debt reserve
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
@ -281,15 +277,15 @@ contract LendingPoolCollateralManager is
**/ **/
function _calculateAvailableCollateralToLiquidate( function _calculateAvailableCollateralToLiquidate(
DataTypes.ReserveData storage collateralReserve, DataTypes.ReserveData storage collateralReserve,
DataTypes.ReserveData storage debtReserve, DataTypes.ReserveCache memory debtReserveCache,
address collateralAsset, address collateralAsset,
address debtAsset, address debtAsset,
uint256 debtToCover, uint256 debtToCover,
uint256 userCollateralBalance uint256 userCollateralBalance,
IPriceOracleGetter oracle
) internal view returns (uint256, uint256) { ) internal view returns (uint256, uint256) {
uint256 collateralAmount = 0; uint256 collateralAmount = 0;
uint256 debtAmountNeeded = 0; uint256 debtAmountNeeded = 0;
IPriceOracleGetter oracle = IPriceOracleGetter(_addressesProvider.getPriceOracle());
AvailableCollateralToLiquidateLocalVars memory vars; AvailableCollateralToLiquidateLocalVars memory vars;
@ -299,7 +295,7 @@ contract LendingPoolCollateralManager is
(, , vars.liquidationBonus, vars.collateralDecimals, ) = collateralReserve (, , vars.liquidationBonus, vars.collateralDecimals, ) = collateralReserve
.configuration .configuration
.getParams(); .getParams();
vars.debtAssetDecimals = debtReserve.configuration.getDecimals(); vars.debtAssetDecimals = debtReserveCache.reserveConfiguration.getDecimalsMemory();
// This is the maximum possible amount of the selected collateral that can be liquidated, given the // This is the maximum possible amount of the selected collateral that can be liquidated, given the
// max amount of liquidatable debt // max amount of liquidatable debt

View File

@ -70,7 +70,7 @@ library ReserveConfiguration {
* @param self The reserve configuration * @param self The reserve configuration
* @return The loan to value * @return The loan to value
**/ **/
function getLtvMemory(DataTypes.ReserveConfigurationMap memory self) internal view returns (uint256) { function getLtvMemory(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) {
return self.data & ~LTV_MASK; return self.data & ~LTV_MASK;
} }
@ -104,18 +104,6 @@ library ReserveConfiguration {
return (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION; return (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION;
} }
/**
* @dev Gets the liquidation threshold of the reserve
* @param self The reserve configuration
* @return The liquidation threshold
**/
function getLiquidationThresholdMemory(DataTypes.ReserveConfigurationMap memory self)
internal
view
returns (uint256)
{
return (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION;
}
/** /**
* @dev Sets the liquidation bonus of the reserve * @dev Sets the liquidation bonus of the reserve
* @param self The reserve configuration * @param self The reserve configuration
@ -172,7 +160,6 @@ library ReserveConfiguration {
return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION; return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION;
} }
/** /**
* @dev Gets the decimals of the underlying asset of the reserve * @dev Gets the decimals of the underlying asset of the reserve
* @param self The reserve configuration * @param self The reserve configuration
@ -180,7 +167,7 @@ library ReserveConfiguration {
**/ **/
function getDecimalsMemory(DataTypes.ReserveConfigurationMap memory self) function getDecimalsMemory(DataTypes.ReserveConfigurationMap memory self)
internal internal
view pure
returns (uint256) returns (uint256)
{ {
return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION; return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION;
@ -336,7 +323,7 @@ library ReserveConfiguration {
**/ **/
function getReserveFactorMemory(DataTypes.ReserveConfigurationMap memory self) function getReserveFactorMemory(DataTypes.ReserveConfigurationMap memory self)
internal internal
view pure
returns (uint256) returns (uint256)
{ {
return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION; return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION;

View File

@ -198,4 +198,36 @@ library GenericLogic {
availableBorrowsETH = availableBorrowsETH.sub(totalDebtInETH); availableBorrowsETH = availableBorrowsETH.sub(totalDebtInETH);
return availableBorrowsETH; return availableBorrowsETH;
} }
/**
* @dev proxy call for calculateUserAccountData as external function.
* Used in LendingPool to work around contract size limit issues
* @param user The address of the user
* @param reservesData Data of all the reserves
* @param userConfig The configuration of the user
* @param reserves The list of the available reserves
* @param oracle The price oracle address
* @return The total collateral and total debt of the user in ETH, the avg ltv, liquidation threshold and the HF
**/
function getUserAccountData(
address user,
mapping(address => DataTypes.ReserveData) storage reservesData,
DataTypes.UserConfigurationMap memory userConfig,
mapping(uint256 => address) storage reserves,
uint256 reservesCount,
address oracle
)
external
view
returns (
uint256,
uint256,
uint256,
uint256,
uint256
)
{
return
calculateUserAccountData(user, reservesData, userConfig, reserves, reservesCount, oracle);
}
} }

View File

@ -186,7 +186,6 @@ library ReserveLogic {
) internal { ) internal {
UpdateInterestRatesLocalVars memory vars; UpdateInterestRatesLocalVars memory vars;
reserveCache.nextTotalVariableDebt = reserveCache.nextScaledVariableDebt.rayMul( reserveCache.nextTotalVariableDebt = reserveCache.nextScaledVariableDebt.rayMul(
reserveCache.nextVariableBorrowIndex reserveCache.nextVariableBorrowIndex
); );
@ -386,10 +385,8 @@ library ReserveLogic {
uint256 stableDebtBurned, uint256 stableDebtBurned,
uint256 variableDebtMinted, uint256 variableDebtMinted,
uint256 variableDebtBurned uint256 variableDebtBurned
) internal { ) internal view {
uint256 scaledVariableDebtMinted = variableDebtMinted.rayDiv(cache.nextVariableBorrowIndex); if (stableDebtMinted != 0 || stableDebtBurned != 0) {
uint256 scaledVariableDebtBurned = variableDebtBurned.rayDiv(cache.nextVariableBorrowIndex);
if (cache.currTotalStableDebt.add(stableDebtMinted) > stableDebtBurned) { if (cache.currTotalStableDebt.add(stableDebtMinted) > stableDebtBurned) {
cache.nextPrincipalStableDebt = cache.nextTotalStableDebt = cache cache.nextPrincipalStableDebt = cache.nextTotalStableDebt = cache
.currTotalStableDebt .currTotalStableDebt
@ -400,11 +397,17 @@ library ReserveLogic {
.getAverageStableRate(); .getAverageStableRate();
} }
} else { } else {
cache.nextPrincipalStableDebt = cache.nextTotalStableDebt = cache.nextAvgStableBorrowRate = 0; cache.nextPrincipalStableDebt = cache.nextTotalStableDebt = cache
.nextAvgStableBorrowRate = 0;
}
} }
if (variableDebtMinted != 0 || variableDebtBurned != 0) {
uint256 scaledVariableDebtMinted = variableDebtMinted.rayDiv(cache.nextVariableBorrowIndex);
uint256 scaledVariableDebtBurned = variableDebtBurned.rayDiv(cache.nextVariableBorrowIndex);
cache.nextScaledVariableDebt = cache.currScaledVariableDebt.add(scaledVariableDebtMinted).sub( cache.nextScaledVariableDebt = cache.currScaledVariableDebt.add(scaledVariableDebtMinted).sub(
scaledVariableDebtBurned scaledVariableDebtBurned
); );
} }
} }
}

View File

@ -16,6 +16,7 @@ import {Helpers} from '../helpers/Helpers.sol';
import {IReserveInterestRateStrategy} from '../../../interfaces/IReserveInterestRateStrategy.sol'; import {IReserveInterestRateStrategy} from '../../../interfaces/IReserveInterestRateStrategy.sol';
import {IVariableDebtToken} from '../../../interfaces/IVariableDebtToken.sol'; import {IVariableDebtToken} from '../../../interfaces/IVariableDebtToken.sol';
import {IStableDebtToken} from '../../../interfaces/IStableDebtToken.sol'; import {IStableDebtToken} from '../../../interfaces/IStableDebtToken.sol';
import {IScaledBalanceToken} from '../../../interfaces/IScaledBalanceToken.sol';
import {IAToken} from '../../../interfaces/IAToken.sol'; import {IAToken} from '../../../interfaces/IAToken.sol';
import {DataTypes} from '../types/DataTypes.sol'; import {DataTypes} from '../types/DataTypes.sol';
import {IPriceOracleGetter} from '../../../interfaces/IPriceOracleGetter.sol'; import {IPriceOracleGetter} from '../../../interfaces/IPriceOracleGetter.sol';
@ -39,14 +40,13 @@ library ValidationLogic {
/** /**
* @dev Validates a deposit action * @dev Validates a deposit action
* @param reserve The reserve object on which the user is depositing * @param reserveCache The cached data of the reserve
* @param amount The amount to be deposited * @param amount The amount to be deposited
*/ */
function validateDeposit( function validateDeposit(DataTypes.ReserveCache memory reserveCache, uint256 amount)
DataTypes.ReserveData storage reserve, internal
DataTypes.ReserveCache memory reserveCache, view
uint256 amount {
) internal view {
(bool isActive, bool isFrozen, , , bool isPaused) = (bool isActive, bool isFrozen, , , bool isPaused) =
reserveCache.reserveConfiguration.getFlagsMemory(); reserveCache.reserveConfiguration.getFlagsMemory();
(, , , uint256 reserveDecimals, ) = reserveCache.reserveConfiguration.getParamsMemory(); (, , , uint256 reserveDecimals, ) = reserveCache.reserveConfiguration.getParamsMemory();
@ -70,16 +70,15 @@ library ValidationLogic {
/** /**
* @dev Validates a withdraw action * @dev Validates a withdraw action
* @param reserve The reserve object * @param reserveCache The cached data of the reserve
* @param amount The amount to be withdrawn * @param amount The amount to be withdrawn
* @param userBalance The balance of the user * @param userBalance The balance of the user
*/ */
function validateWithdraw( function validateWithdraw(
DataTypes.ReserveData storage reserve,
DataTypes.ReserveCache memory reserveCache, DataTypes.ReserveCache memory reserveCache,
uint256 amount, uint256 amount,
uint256 userBalance uint256 userBalance
) internal view { ) internal pure {
require(amount != 0, Errors.VL_INVALID_AMOUNT); require(amount != 0, Errors.VL_INVALID_AMOUNT);
require(amount <= userBalance, Errors.VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE); require(amount <= userBalance, Errors.VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE);
@ -245,21 +244,20 @@ library ValidationLogic {
/** /**
* @dev Validates a repay action * @dev Validates a repay action
* @param reserve The reserve state from which the user is repaying * @param reserveCache The cached data of the reserve
* @param amountSent The amount sent for the repayment. Can be an actual value or uint(-1) * @param amountSent The amount sent for the repayment. Can be an actual value or uint(-1)
* @param onBehalfOf The address of the user msg.sender is repaying for * @param onBehalfOf The address of the user msg.sender is repaying for
* @param stableDebt The borrow balance of the user * @param stableDebt The borrow balance of the user
* @param variableDebt The borrow balance of the user * @param variableDebt The borrow balance of the user
*/ */
function validateRepay( function validateRepay(
DataTypes.ReserveData storage reserve,
DataTypes.ReserveCache memory reserveCache, DataTypes.ReserveCache memory reserveCache,
uint256 amountSent, uint256 amountSent,
DataTypes.InterestRateMode rateMode, DataTypes.InterestRateMode rateMode,
address onBehalfOf, address onBehalfOf,
uint256 stableDebt, uint256 stableDebt,
uint256 variableDebt uint256 variableDebt
) external view { ) internal view {
(bool isActive, , , , bool isPaused) = reserveCache.reserveConfiguration.getFlagsMemory(); (bool isActive, , , , bool isPaused) = reserveCache.reserveConfiguration.getFlagsMemory();
require(isActive, Errors.VL_NO_ACTIVE_RESERVE); require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
require(!isPaused, Errors.VL_RESERVE_PAUSED); require(!isPaused, Errors.VL_RESERVE_PAUSED);
@ -371,12 +369,12 @@ library ValidationLogic {
/** /**
* @dev Validates the action of setting an asset as collateral * @dev Validates the action of setting an asset as collateral
* @param reserve The state of the reserve that the user is enabling or disabling as collateral * @param reserveCache The cached data of the reserve
*/ */
function validateSetUseReserveAsCollateral( function validateSetUseReserveAsCollateral(DataTypes.ReserveCache memory reserveCache)
DataTypes.ReserveData storage reserve, external
DataTypes.ReserveCache memory reserveCache view
) external view { {
uint256 underlyingBalance = IERC20(reserveCache.aTokenAddress).balanceOf(msg.sender); uint256 underlyingBalance = IERC20(reserveCache.aTokenAddress).balanceOf(msg.sender);
(bool isActive, , , , bool isPaused) = reserveCache.reserveConfiguration.getFlagsMemory(); (bool isActive, , , , bool isPaused) = reserveCache.reserveConfiguration.getFlagsMemory();
@ -395,68 +393,88 @@ library ValidationLogic {
address[] memory assets, address[] memory assets,
uint256[] memory amounts, uint256[] memory amounts,
mapping(address => DataTypes.ReserveData) storage reservesData mapping(address => DataTypes.ReserveData) storage reservesData
) external view { ) internal view {
for (uint256 i = 0; i < assets.length; i++) { for (uint256 i = 0; i < assets.length; i++) {
require(!reservesData[assets[i]].configuration.getPaused(), Errors.VL_RESERVE_PAUSED); require(!reservesData[assets[i]].configuration.getPaused(), Errors.VL_RESERVE_PAUSED);
} }
require(assets.length == amounts.length, Errors.VL_INCONSISTENT_FLASHLOAN_PARAMS); require(assets.length == amounts.length, Errors.VL_INCONSISTENT_FLASHLOAN_PARAMS);
} }
struct ValidateLiquidationCallLocalVars {
uint256 healthFactor;
bool collateralReserveActive;
bool collateralReservePaused;
bool principalReserveActive;
bool principalReservePaused;
bool isCollateralEnabled;
}
/** /**
* @dev Validates the liquidation action * @dev Validates the liquidation action
* @param collateralReserve The reserve data of the collateral * @param collateralReserve The reserve data of the collateral
* @param principalReserve The reserve data of the principal
* @param userConfig The user configuration * @param userConfig The user configuration
* @param userHealthFactor The user's health factor * @param totalDebt Total debt balance of the user
* @param userStableDebt Total stable debt balance of the user
* @param userVariableDebt Total variable debt balance of the user
**/ **/
function validateLiquidationCall( function validateLiquidationCall(
DataTypes.ReserveData storage collateralReserve, DataTypes.ReserveData storage collateralReserve,
DataTypes.ReserveData storage principalReserve,
DataTypes.ReserveCache memory collateralReserveCache,
DataTypes.ReserveCache memory principalReserveCache, DataTypes.ReserveCache memory principalReserveCache,
uint256 totalDebt,
address user,
mapping(address => DataTypes.ReserveData) storage reservesData,
DataTypes.UserConfigurationMap storage userConfig, DataTypes.UserConfigurationMap storage userConfig,
uint256 userHealthFactor, mapping(uint256 => address) storage reserves,
uint256 userStableDebt, uint256 reservesCount,
uint256 userVariableDebt address oracle
) internal view returns (uint256, string memory) { ) internal view returns (uint256, string memory) {
(bool collateralReserveActive, , , , bool collateralReservePaused) = ValidateLiquidationCallLocalVars memory vars;
collateralReserveCache.reserveConfiguration.getFlagsMemory();
(bool principalReserveActive, , , , bool principalReservePaused) = (vars.collateralReserveActive, , , , vars.collateralReservePaused) = collateralReserve
collateralReserveCache.reserveConfiguration.getFlagsMemory(); .configuration
.getFlagsMemory();
if (!collateralReserveActive || !principalReserveActive) { (vars.principalReserveActive, , , , vars.principalReservePaused) = principalReserveCache
.reserveConfiguration
.getFlagsMemory();
if (!vars.collateralReserveActive || !vars.principalReserveActive) {
return ( return (
uint256(Errors.CollateralManagerErrors.NO_ACTIVE_RESERVE), uint256(Errors.CollateralManagerErrors.NO_ACTIVE_RESERVE),
Errors.VL_NO_ACTIVE_RESERVE Errors.VL_NO_ACTIVE_RESERVE
); );
} }
if (collateralReservePaused || principalReservePaused) { if (vars.collateralReservePaused || vars.principalReservePaused) {
return (uint256(Errors.CollateralManagerErrors.PAUSED_RESERVE), Errors.VL_RESERVE_PAUSED); return (uint256(Errors.CollateralManagerErrors.PAUSED_RESERVE), Errors.VL_RESERVE_PAUSED);
} }
if (userHealthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD) { (, , , , vars.healthFactor) = GenericLogic.calculateUserAccountData(
user,
reservesData,
userConfig,
reserves,
reservesCount,
oracle
);
if (vars.healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD) {
return ( return (
uint256(Errors.CollateralManagerErrors.HEALTH_FACTOR_ABOVE_THRESHOLD), uint256(Errors.CollateralManagerErrors.HEALTH_FACTOR_ABOVE_THRESHOLD),
Errors.LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD Errors.LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD
); );
} }
bool isCollateralEnabled = vars.isCollateralEnabled =
collateralReserveCache.reserveConfiguration.getLiquidationThresholdMemory() > 0 && collateralReserve.configuration.getLiquidationThreshold() > 0 &&
userConfig.isUsingAsCollateral(collateralReserve.id); userConfig.isUsingAsCollateral(collateralReserve.id);
//if collateral isn't enabled as collateral by user, it cannot be liquidated //if collateral isn't enabled as collateral by user, it cannot be liquidated
if (!isCollateralEnabled) { if (!vars.isCollateralEnabled) {
return ( return (
uint256(Errors.CollateralManagerErrors.COLLATERAL_CANNOT_BE_LIQUIDATED), uint256(Errors.CollateralManagerErrors.COLLATERAL_CANNOT_BE_LIQUIDATED),
Errors.LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED Errors.LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED
); );
} }
if (userStableDebt == 0 && userVariableDebt == 0) { if (totalDebt == 0) {
return ( return (
uint256(Errors.CollateralManagerErrors.CURRRENCY_NOT_BORROWED), uint256(Errors.CollateralManagerErrors.CURRRENCY_NOT_BORROWED),
Errors.LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER Errors.LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER
@ -482,7 +500,7 @@ library ValidationLogic {
mapping(uint256 => address) storage reserves, mapping(uint256 => address) storage reserves,
uint256 reservesCount, uint256 reservesCount,
address oracle address oracle
) internal view { ) external view {
(, , , , uint256 healthFactor) = (, , , , uint256 healthFactor) =
GenericLogic.calculateUserAccountData( GenericLogic.calculateUserAccountData(
from, from,

View File

@ -188,7 +188,8 @@ export const deployAaveLibraries = async (
return { return {
['__$de8c0cf1a7d7c36c802af9a64fb9d86036$__']: validationLogic.address, ['__$de8c0cf1a7d7c36c802af9a64fb9d86036$__']: validationLogic.address,
['__$22cd43a9dda9ce44e9b92ba393b88fb9ac$__']: reserveLogic.address, ['__$22cd43a9dda9ce44e9b92ba393b88fb9ac$__']: reserveLogic.address,
}; ["__$52a8a86ab43135662ff256bbc95497e8e3$__"]: genericLogic.address,
}
}; };
export const deployLendingPool = async (verify?: boolean) => { export const deployLendingPool = async (verify?: boolean) => {