mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Merge branch 'master' into 30-collateral-swap
This commit is contained in:
commit
8d391b9ab5
|
@ -431,6 +431,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
uint256 purchaseAmount,
|
uint256 purchaseAmount,
|
||||||
bool receiveAToken
|
bool receiveAToken
|
||||||
) external override {
|
) external override {
|
||||||
|
|
||||||
address liquidationManager = _addressesProvider.getLendingPoolLiquidationManager();
|
address liquidationManager = _addressesProvider.getLendingPoolLiquidationManager();
|
||||||
|
|
||||||
//solium-disable-next-line
|
//solium-disable-next-line
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {PercentageMath} from '../libraries/math/PercentageMath.sol';
|
||||||
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
|
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
|
||||||
import {ISwapAdapter} from '../interfaces/ISwapAdapter.sol';
|
import {ISwapAdapter} from '../interfaces/ISwapAdapter.sol';
|
||||||
import {Errors} from '../libraries/helpers/Errors.sol';
|
import {Errors} from '../libraries/helpers/Errors.sol';
|
||||||
|
import {ValidationLogic} from '../libraries/logic/ValidationLogic.sol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title LendingPoolLiquidationManager contract
|
* @title LendingPoolLiquidationManager contract
|
||||||
|
@ -89,17 +90,6 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
|
||||||
uint256 swappedCollateralAmount
|
uint256 swappedCollateralAmount
|
||||||
);
|
);
|
||||||
|
|
||||||
enum LiquidationErrors {
|
|
||||||
NO_ERROR,
|
|
||||||
NO_COLLATERAL_AVAILABLE,
|
|
||||||
COLLATERAL_CANNOT_BE_LIQUIDATED,
|
|
||||||
CURRRENCY_NOT_BORROWED,
|
|
||||||
HEALTH_FACTOR_ABOVE_THRESHOLD,
|
|
||||||
NOT_ENOUGH_LIQUIDITY,
|
|
||||||
HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD,
|
|
||||||
INVALID_EQUAL_ASSETS_TO_SWAP
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LiquidationCallLocalVars {
|
struct LiquidationCallLocalVars {
|
||||||
uint256 userCollateralBalance;
|
uint256 userCollateralBalance;
|
||||||
uint256 userStableDebt;
|
uint256 userStableDebt;
|
||||||
|
@ -116,6 +106,8 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
|
||||||
IAToken collateralAtoken;
|
IAToken collateralAtoken;
|
||||||
bool isCollateralEnabled;
|
bool isCollateralEnabled;
|
||||||
address principalAToken;
|
address principalAToken;
|
||||||
|
uint256 errorCode;
|
||||||
|
string errorMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -142,8 +134,8 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
|
||||||
uint256 purchaseAmount,
|
uint256 purchaseAmount,
|
||||||
bool receiveAToken
|
bool receiveAToken
|
||||||
) external returns (uint256, string memory) {
|
) external returns (uint256, string memory) {
|
||||||
ReserveLogic.ReserveData storage principalReserve = reserves[principal];
|
|
||||||
ReserveLogic.ReserveData storage collateralReserve = reserves[collateral];
|
ReserveLogic.ReserveData storage collateralReserve = reserves[collateral];
|
||||||
|
ReserveLogic.ReserveData storage principalReserve = reserves[principal];
|
||||||
UserConfiguration.Map storage userConfig = usersConfig[user];
|
UserConfiguration.Map storage userConfig = usersConfig[user];
|
||||||
|
|
||||||
LiquidationCallLocalVars memory vars;
|
LiquidationCallLocalVars memory vars;
|
||||||
|
@ -156,43 +148,29 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
|
||||||
addressesProvider.getPriceOracle()
|
addressesProvider.getPriceOracle()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (vars.healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD) {
|
|
||||||
return (
|
|
||||||
uint256(LiquidationErrors.HEALTH_FACTOR_ABOVE_THRESHOLD),
|
|
||||||
Errors.HEALTH_FACTOR_NOT_BELOW_THRESHOLD
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
vars.collateralAtoken = IAToken(collateralReserve.aTokenAddress);
|
|
||||||
|
|
||||||
vars.userCollateralBalance = vars.collateralAtoken.balanceOf(user);
|
|
||||||
|
|
||||||
vars.isCollateralEnabled =
|
|
||||||
collateralReserve.configuration.getLiquidationThreshold() > 0 &&
|
|
||||||
userConfig.isUsingAsCollateral(collateralReserve.id);
|
|
||||||
|
|
||||||
//if collateral isn't enabled as collateral by user, it cannot be liquidated
|
|
||||||
if (!vars.isCollateralEnabled) {
|
|
||||||
return (
|
|
||||||
uint256(LiquidationErrors.COLLATERAL_CANNOT_BE_LIQUIDATED),
|
|
||||||
Errors.COLLATERAL_CANNOT_BE_LIQUIDATED
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if the user hasn't borrowed the specific currency defined by asset, it cannot be liquidated
|
//if the user hasn't borrowed the specific currency defined by asset, it cannot be liquidated
|
||||||
(vars.userStableDebt, vars.userVariableDebt) = Helpers.getUserCurrentDebt(
|
(vars.userStableDebt, vars.userVariableDebt) = Helpers.getUserCurrentDebt(
|
||||||
user,
|
user,
|
||||||
principalReserve
|
principalReserve
|
||||||
);
|
);
|
||||||
|
|
||||||
if (vars.userStableDebt == 0 && vars.userVariableDebt == 0) {
|
(vars.errorCode, vars.errorMsg) = ValidationLogic.validateLiquidationCall(
|
||||||
return (
|
collateralReserve,
|
||||||
uint256(LiquidationErrors.CURRRENCY_NOT_BORROWED),
|
principalReserve,
|
||||||
Errors.SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER
|
userConfig,
|
||||||
);
|
vars.healthFactor,
|
||||||
|
vars.userStableDebt,
|
||||||
|
vars.userVariableDebt
|
||||||
|
);
|
||||||
|
|
||||||
|
if (Errors.LiquidationErrors(vars.errorCode) != Errors.LiquidationErrors.NO_ERROR) {
|
||||||
|
return (vars.errorCode, vars.errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
//all clear - calculate the max principal amount that can be liquidated
|
vars.collateralAtoken = IAToken(collateralReserve.aTokenAddress);
|
||||||
|
|
||||||
|
vars.userCollateralBalance = vars.collateralAtoken.balanceOf(user);
|
||||||
|
|
||||||
vars.maxPrincipalAmountToLiquidate = vars.userStableDebt.add(vars.userVariableDebt).percentMul(
|
vars.maxPrincipalAmountToLiquidate = vars.userStableDebt.add(vars.userVariableDebt).percentMul(
|
||||||
LIQUIDATION_CLOSE_FACTOR_PERCENT
|
LIQUIDATION_CLOSE_FACTOR_PERCENT
|
||||||
);
|
);
|
||||||
|
@ -228,7 +206,7 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
|
||||||
);
|
);
|
||||||
if (currentAvailableCollateral < vars.maxCollateralToLiquidate) {
|
if (currentAvailableCollateral < vars.maxCollateralToLiquidate) {
|
||||||
return (
|
return (
|
||||||
uint256(LiquidationErrors.NOT_ENOUGH_LIQUIDITY),
|
uint256(Errors.LiquidationErrors.NOT_ENOUGH_LIQUIDITY),
|
||||||
Errors.NOT_ENOUGH_LIQUIDITY_TO_LIQUIDATE
|
Errors.NOT_ENOUGH_LIQUIDITY_TO_LIQUIDATE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -295,7 +273,7 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
|
||||||
receiveAToken
|
receiveAToken
|
||||||
);
|
);
|
||||||
|
|
||||||
return (uint256(LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
|
return (uint256(Errors.LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -318,9 +296,8 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
|
||||||
address receiver,
|
address receiver,
|
||||||
bytes calldata params
|
bytes calldata params
|
||||||
) external returns (uint256, string memory) {
|
) external returns (uint256, string memory) {
|
||||||
ReserveLogic.ReserveData storage debtReserve = reserves[principal];
|
|
||||||
ReserveLogic.ReserveData storage collateralReserve = reserves[collateral];
|
ReserveLogic.ReserveData storage collateralReserve = reserves[collateral];
|
||||||
|
ReserveLogic.ReserveData storage debtReserve = reserves[principal];
|
||||||
UserConfiguration.Map storage userConfig = usersConfig[user];
|
UserConfiguration.Map storage userConfig = usersConfig[user];
|
||||||
|
|
||||||
LiquidationCallLocalVars memory vars;
|
LiquidationCallLocalVars memory vars;
|
||||||
|
@ -333,36 +310,20 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
|
||||||
addressesProvider.getPriceOracle()
|
addressesProvider.getPriceOracle()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
|
||||||
msg.sender != user && vars.healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
uint256(LiquidationErrors.HEALTH_FACTOR_ABOVE_THRESHOLD),
|
|
||||||
Errors.HEALTH_FACTOR_NOT_BELOW_THRESHOLD
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg.sender != user) {
|
|
||||||
vars.isCollateralEnabled =
|
|
||||||
collateralReserve.configuration.getLiquidationThreshold() > 0 &&
|
|
||||||
userConfig.isUsingAsCollateral(collateralReserve.id);
|
|
||||||
|
|
||||||
//if collateral isn't enabled as collateral by user, it cannot be liquidated
|
|
||||||
if (!vars.isCollateralEnabled) {
|
|
||||||
return (
|
|
||||||
uint256(LiquidationErrors.COLLATERAL_CANNOT_BE_LIQUIDATED),
|
|
||||||
Errors.COLLATERAL_CANNOT_BE_LIQUIDATED
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(vars.userStableDebt, vars.userVariableDebt) = Helpers.getUserCurrentDebt(user, debtReserve);
|
(vars.userStableDebt, vars.userVariableDebt) = Helpers.getUserCurrentDebt(user, debtReserve);
|
||||||
|
|
||||||
if (vars.userStableDebt == 0 && vars.userVariableDebt == 0) {
|
(vars.errorCode, vars.errorMsg) = ValidationLogic.validateRepayWithCollateral(
|
||||||
return (
|
collateralReserve,
|
||||||
uint256(LiquidationErrors.CURRRENCY_NOT_BORROWED),
|
debtReserve,
|
||||||
Errors.SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER
|
userConfig,
|
||||||
);
|
user,
|
||||||
|
vars.healthFactor,
|
||||||
|
vars.userStableDebt,
|
||||||
|
vars.userVariableDebt
|
||||||
|
);
|
||||||
|
|
||||||
|
if (Errors.LiquidationErrors(vars.errorCode) != Errors.LiquidationErrors.NO_ERROR) {
|
||||||
|
return (vars.errorCode, vars.errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
vars.maxPrincipalAmountToLiquidate = vars.userStableDebt.add(vars.userVariableDebt);
|
vars.maxPrincipalAmountToLiquidate = vars.userStableDebt.add(vars.userVariableDebt);
|
||||||
|
@ -447,7 +408,7 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
|
||||||
vars.maxCollateralToLiquidate
|
vars.maxCollateralToLiquidate
|
||||||
);
|
);
|
||||||
|
|
||||||
return (uint256(LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
|
return (uint256(Errors.LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AvailableCollateralToLiquidateLocalVars {
|
struct AvailableCollateralToLiquidateLocalVars {
|
||||||
|
@ -534,7 +495,7 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
|
||||||
bytes calldata params
|
bytes calldata params
|
||||||
) external returns (uint256, string memory) {
|
) external returns (uint256, string memory) {
|
||||||
if (fromAsset == toAsset) {
|
if (fromAsset == toAsset) {
|
||||||
return (uint256(LiquidationErrors.INVALID_EQUAL_ASSETS_TO_SWAP), Errors.INVALID_EQUAL_ASSETS_TO_SWAP);
|
return (uint256(Errors.LiquidationErrors.INVALID_EQUAL_ASSETS_TO_SWAP), Errors.INVALID_EQUAL_ASSETS_TO_SWAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReserveLogic.ReserveData storage fromReserve = reserves[fromAsset];
|
ReserveLogic.ReserveData storage fromReserve = reserves[fromAsset];
|
||||||
|
@ -580,11 +541,11 @@ contract LendingPoolLiquidationManager is VersionedInitializable {
|
||||||
|
|
||||||
if (healthFactor < GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD) {
|
if (healthFactor < GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD) {
|
||||||
return (
|
return (
|
||||||
uint256(LiquidationErrors.HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD),
|
uint256(Errors.LiquidationErrors.HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD),
|
||||||
Errors.HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD
|
Errors.HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (uint256(LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
|
return (uint256(Errors.LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,4 +76,16 @@ library Errors {
|
||||||
string public constant MULTIPLICATION_OVERFLOW = '44';
|
string public constant MULTIPLICATION_OVERFLOW = '44';
|
||||||
string public constant ADDITION_OVERFLOW = '45';
|
string public constant ADDITION_OVERFLOW = '45';
|
||||||
string public constant DIVISION_BY_ZERO = '46';
|
string public constant DIVISION_BY_ZERO = '46';
|
||||||
|
|
||||||
|
enum LiquidationErrors {
|
||||||
|
NO_ERROR,
|
||||||
|
NO_COLLATERAL_AVAILABLE,
|
||||||
|
COLLATERAL_CANNOT_BE_LIQUIDATED,
|
||||||
|
CURRRENCY_NOT_BORROWED,
|
||||||
|
HEALTH_FACTOR_ABOVE_THRESHOLD,
|
||||||
|
NOT_ENOUGH_LIQUIDITY,
|
||||||
|
NO_ACTIVE_RESERVE,
|
||||||
|
HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD,
|
||||||
|
INVALID_EQUAL_ASSETS_TO_SWAP
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol';
|
||||||
import {UserConfiguration} from '../configuration/UserConfiguration.sol';
|
import {UserConfiguration} from '../configuration/UserConfiguration.sol';
|
||||||
import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol';
|
import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol';
|
||||||
import {Errors} from '../helpers/Errors.sol';
|
import {Errors} from '../helpers/Errors.sol';
|
||||||
|
import {Helpers} from '../helpers/Helpers.sol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title ReserveLogic library
|
* @title ReserveLogic library
|
||||||
|
@ -329,4 +330,116 @@ library ValidationLogic {
|
||||||
require(premium > 0, Errors.REQUESTED_AMOUNT_TOO_SMALL);
|
require(premium > 0, Errors.REQUESTED_AMOUNT_TOO_SMALL);
|
||||||
require(mode <= uint256(ReserveLogic.InterestRateMode.VARIABLE), Errors.INVALID_FLASHLOAN_MODE);
|
require(mode <= uint256(ReserveLogic.InterestRateMode.VARIABLE), Errors.INVALID_FLASHLOAN_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Validates the liquidationCall() action
|
||||||
|
* @param collateralReserve The reserve data of the collateral
|
||||||
|
* @param principalReserve The reserve data of the principal
|
||||||
|
* @param userConfig The user configuration
|
||||||
|
* @param userHealthFactor The user's health factor
|
||||||
|
* @param userStableDebt Total stable debt balance of the user
|
||||||
|
* @param userVariableDebt Total variable debt balance of the user
|
||||||
|
**/
|
||||||
|
function validateLiquidationCall(
|
||||||
|
ReserveLogic.ReserveData storage collateralReserve,
|
||||||
|
ReserveLogic.ReserveData storage principalReserve,
|
||||||
|
UserConfiguration.Map storage userConfig,
|
||||||
|
uint256 userHealthFactor,
|
||||||
|
uint256 userStableDebt,
|
||||||
|
uint256 userVariableDebt
|
||||||
|
) internal view returns(uint256, string memory) {
|
||||||
|
if ( !collateralReserve.configuration.getActive() || !principalReserve.configuration.getActive()) {
|
||||||
|
return (
|
||||||
|
uint256(Errors.LiquidationErrors.NO_ACTIVE_RESERVE),
|
||||||
|
Errors.NO_ACTIVE_RESERVE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userHealthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD) {
|
||||||
|
return (
|
||||||
|
uint256(Errors.LiquidationErrors.HEALTH_FACTOR_ABOVE_THRESHOLD),
|
||||||
|
Errors.HEALTH_FACTOR_NOT_BELOW_THRESHOLD
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isCollateralEnabled =
|
||||||
|
collateralReserve.configuration.getLiquidationThreshold() > 0 &&
|
||||||
|
userConfig.isUsingAsCollateral(collateralReserve.id);
|
||||||
|
|
||||||
|
//if collateral isn't enabled as collateral by user, it cannot be liquidated
|
||||||
|
if (!isCollateralEnabled) {
|
||||||
|
return (
|
||||||
|
uint256(Errors.LiquidationErrors.COLLATERAL_CANNOT_BE_LIQUIDATED),
|
||||||
|
Errors.COLLATERAL_CANNOT_BE_LIQUIDATED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userStableDebt == 0 && userVariableDebt == 0) {
|
||||||
|
return (
|
||||||
|
uint256(Errors.LiquidationErrors.CURRRENCY_NOT_BORROWED),
|
||||||
|
Errors.SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uint256(Errors.LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Validates the repayWithCollateral() action
|
||||||
|
* @param collateralReserve The reserve data of the collateral
|
||||||
|
* @param principalReserve The reserve data of the principal
|
||||||
|
* @param userConfig The user configuration
|
||||||
|
* @param user The address of the user
|
||||||
|
* @param userHealthFactor The user's health factor
|
||||||
|
* @param userStableDebt Total stable debt balance of the user
|
||||||
|
* @param userVariableDebt Total variable debt balance of the user
|
||||||
|
**/
|
||||||
|
function validateRepayWithCollateral(
|
||||||
|
ReserveLogic.ReserveData storage collateralReserve,
|
||||||
|
ReserveLogic.ReserveData storage principalReserve,
|
||||||
|
UserConfiguration.Map storage userConfig,
|
||||||
|
address user,
|
||||||
|
uint256 userHealthFactor,
|
||||||
|
uint256 userStableDebt,
|
||||||
|
uint256 userVariableDebt
|
||||||
|
) internal view returns(uint256, string memory) {
|
||||||
|
if ( !collateralReserve.configuration.getActive() || !principalReserve.configuration.getActive()) {
|
||||||
|
return (
|
||||||
|
uint256(Errors.LiquidationErrors.NO_ACTIVE_RESERVE),
|
||||||
|
Errors.NO_ACTIVE_RESERVE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
msg.sender != user && userHealthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
uint256(Errors.LiquidationErrors.HEALTH_FACTOR_ABOVE_THRESHOLD),
|
||||||
|
Errors.HEALTH_FACTOR_NOT_BELOW_THRESHOLD
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.sender != user) {
|
||||||
|
bool isCollateralEnabled =
|
||||||
|
collateralReserve.configuration.getLiquidationThreshold() > 0 &&
|
||||||
|
userConfig.isUsingAsCollateral(collateralReserve.id);
|
||||||
|
|
||||||
|
//if collateral isn't enabled as collateral by user, it cannot be liquidated
|
||||||
|
if (!isCollateralEnabled) {
|
||||||
|
return (
|
||||||
|
uint256(Errors.LiquidationErrors.COLLATERAL_CANNOT_BE_LIQUIDATED),
|
||||||
|
Errors.COLLATERAL_CANNOT_BE_LIQUIDATED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userStableDebt == 0 && userVariableDebt == 0) {
|
||||||
|
return (
|
||||||
|
uint256(Errors.LiquidationErrors.CURRRENCY_NOT_BORROWED),
|
||||||
|
Errors.SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uint256(Errors.LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {makeSuite} from './helpers/make-suite';
|
||||||
import {ProtocolErrors, RateMode} from '../helpers/types';
|
import {ProtocolErrors, RateMode} from '../helpers/types';
|
||||||
import {calcExpectedStableDebtTokenBalance} from './helpers/utils/calculations';
|
import {calcExpectedStableDebtTokenBalance} from './helpers/utils/calculations';
|
||||||
import {getUserData} from './helpers/utils/helpers';
|
import {getUserData} from './helpers/utils/helpers';
|
||||||
|
import {parseEther} from 'ethers/lib/utils';
|
||||||
|
|
||||||
const chai = require('chai');
|
const chai = require('chai');
|
||||||
|
|
||||||
|
@ -23,6 +24,26 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
|
||||||
BigNumber.config({DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP});
|
BigNumber.config({DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumber.ROUND_HALF_UP});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("It's not possible to liquidate on a non-active collateral or a non active principal", async () => {
|
||||||
|
const {configurator, weth, pool, users, dai} = testEnv;
|
||||||
|
const user = users[1];
|
||||||
|
await configurator.deactivateReserve(weth.address);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
pool.liquidationCall(weth.address, dai.address, user.address, parseEther('1000'), false)
|
||||||
|
).to.be.revertedWith('2');
|
||||||
|
|
||||||
|
await configurator.activateReserve(weth.address);
|
||||||
|
|
||||||
|
await configurator.deactivateReserve(dai.address);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
pool.liquidationCall(weth.address, dai.address, user.address, parseEther('1000'), false)
|
||||||
|
).to.be.revertedWith('2');
|
||||||
|
|
||||||
|
await configurator.activateReserve(dai.address);
|
||||||
|
});
|
||||||
|
|
||||||
it('LIQUIDATION - Deposits WETH, borrows DAI', async () => {
|
it('LIQUIDATION - Deposits WETH, borrows DAI', async () => {
|
||||||
const {dai, weth, users, pool, oracle} = testEnv;
|
const {dai, weth, users, pool, oracle} = testEnv;
|
||||||
const depositor = users[0];
|
const depositor = users[0];
|
||||||
|
|
|
@ -39,6 +39,44 @@ export const expectRepayWithCollateralEvent = (
|
||||||
};
|
};
|
||||||
|
|
||||||
makeSuite('LendingPool. repayWithCollateral()', (testEnv: TestEnv) => {
|
makeSuite('LendingPool. repayWithCollateral()', (testEnv: TestEnv) => {
|
||||||
|
it("It's not possible to repayWithCollateral() on a non-active collateral or a non active principal", async () => {
|
||||||
|
const {configurator, weth, pool, users, dai, mockSwapAdapter} = testEnv;
|
||||||
|
const user = users[1];
|
||||||
|
await configurator.deactivateReserve(weth.address);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
pool
|
||||||
|
.connect(user.signer)
|
||||||
|
.repayWithCollateral(
|
||||||
|
weth.address,
|
||||||
|
dai.address,
|
||||||
|
user.address,
|
||||||
|
parseEther('100'),
|
||||||
|
mockSwapAdapter.address,
|
||||||
|
'0x'
|
||||||
|
)
|
||||||
|
).to.be.revertedWith('2');
|
||||||
|
|
||||||
|
await configurator.activateReserve(weth.address);
|
||||||
|
|
||||||
|
await configurator.deactivateReserve(dai.address);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
pool
|
||||||
|
.connect(user.signer)
|
||||||
|
.repayWithCollateral(
|
||||||
|
weth.address,
|
||||||
|
dai.address,
|
||||||
|
user.address,
|
||||||
|
parseEther('100'),
|
||||||
|
mockSwapAdapter.address,
|
||||||
|
'0x'
|
||||||
|
)
|
||||||
|
).to.be.revertedWith('2');
|
||||||
|
|
||||||
|
await configurator.activateReserve(dai.address);
|
||||||
|
});
|
||||||
|
|
||||||
it('User 1 provides some liquidity for others to borrow', async () => {
|
it('User 1 provides some liquidity for others to borrow', async () => {
|
||||||
const {pool, weth, dai, usdc, deployer} = testEnv;
|
const {pool, weth, dai, usdc, deployer} = testEnv;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user