Merge branch 'master' into 40-refactor-the-storage-of-lp

This commit is contained in:
The3D 2020-09-21 09:31:54 +02:00
commit 7c5de62910
31 changed files with 2688 additions and 8839 deletions

View File

@ -2,6 +2,7 @@ import {usePlugin} from '@nomiclabs/buidler/config';
// @ts-ignore
import {accounts} from './test-wallets.js';
import {eEthereumNetwork} from './helpers/types';
import {BUIDLEREVM_CHAINID, COVERAGE_CHAINID} from './helpers/buidler-constants';
usePlugin('@nomiclabs/buidler-ethers');
usePlugin('buidler-typechain');
@ -9,8 +10,6 @@ usePlugin('solidity-coverage');
usePlugin('@nomiclabs/buidler-waffle');
usePlugin('@nomiclabs/buidler-etherscan');
//usePlugin('buidler-gas-reporter');
const BUIDLEREVM_CHAINID = 31337;
const COVERAGE_CHAINID = 1337;
const DEFAULT_BLOCK_GAS_LIMIT = 10000000;
const DEFAULT_GAS_PRICE = 10;
const HARDFORK = 'istanbul';

View File

@ -21,8 +21,8 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
bytes32 private constant LENDING_POOL = 'LENDING_POOL';
bytes32 private constant LENDING_POOL_CORE = 'LENDING_POOL_CORE';
bytes32 private constant LENDING_POOL_CONFIGURATOR = 'LENDING_POOL_CONFIGURATOR';
bytes32 private constant LENDING_POOL_MANAGER = 'LENDING_POOL_MANAGER';
bytes32 private constant LENDING_POOL_LIQUIDATION_MANAGER = 'LIQUIDATION_MANAGER';
bytes32 private constant AAVE_ADMIN = 'AAVE_ADMIN';
bytes32 private constant LENDING_POOL_COLLATERAL_MANAGER = 'COLLATERAL_MANAGER';
bytes32 private constant LENDING_POOL_FLASHLOAN_PROVIDER = 'FLASHLOAN_PROVIDER';
bytes32 private constant DATA_PROVIDER = 'DATA_PROVIDER';
bytes32 private constant ETHEREUM_ADDRESS = 'ETHEREUM_ADDRESS';
@ -65,23 +65,23 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
}
/**
* @dev returns the address of the LendingPoolLiquidationManager. Since the manager is used
* @dev returns the address of the LendingPoolCollateralManager. Since the manager is used
* through delegateCall within the LendingPool contract, the proxy contract pattern does not work properly hence
* the addresses are changed directly.
* @return the address of the Lending pool liquidation manager
* @return the address of the Lending pool collateral manager
**/
function getLendingPoolLiquidationManager() external override view returns (address) {
return _addresses[LENDING_POOL_LIQUIDATION_MANAGER];
function getLendingPoolCollateralManager() external override view returns (address) {
return _addresses[LENDING_POOL_COLLATERAL_MANAGER];
}
/**
* @dev updates the address of the Lending pool liquidation manager
* @param manager the new lending pool liquidation manager address
* @dev updates the address of the Lending pool collateral manager
* @param manager the new lending pool collateral manager address
**/
function setLendingPoolLiquidationManager(address manager) external override onlyOwner {
_addresses[LENDING_POOL_LIQUIDATION_MANAGER] = manager;
emit LendingPoolLiquidationManagerUpdated(manager);
function setLendingPoolCollateralManager(address manager) external override onlyOwner {
_addresses[LENDING_POOL_COLLATERAL_MANAGER] = manager;
emit LendingPoolCollateralManagerUpdated(manager);
}
/**
@ -89,13 +89,13 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
* hence the upgradable proxy pattern is not used
**/
function getLendingPoolManager() external override view returns (address) {
return _addresses[LENDING_POOL_MANAGER];
function getAaveAdmin() external override view returns (address) {
return _addresses[AAVE_ADMIN];
}
function setLendingPoolManager(address lendingPoolManager) external override onlyOwner {
_addresses[LENDING_POOL_MANAGER] = lendingPoolManager;
emit LendingPoolManagerUpdated(lendingPoolManager);
function setAaveAdmin(address aaveAdmin) external override onlyOwner {
_addresses[AAVE_ADMIN] = aaveAdmin;
emit AaveAdminUpdated(aaveAdmin);
}
function getPriceOracle() external override view returns (address) {

View File

@ -0,0 +1,11 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
interface IAaveIncentivesController {
function handleAction(
address user,
uint256 userBalance,
uint256 totalSupply
) external;
}

View File

@ -111,7 +111,7 @@ interface ILendingPool {
);
/**
* @dev these events are not emitted directly by the LendingPool
* but they are declared here as the LendingPoolLiquidationManager
* but they are declared here as the LendingPoolCollateralManager
* is executed using a delegateCall().
* This allows to have the events in the generated ABI for LendingPool.
**/
@ -439,5 +439,5 @@ interface ILendingPool {
/**
* @dev Returns if the LendingPool is paused
*/
function paused() external view returns(bool);
function paused() external view returns (bool);
}

View File

@ -9,9 +9,9 @@ pragma solidity ^0.6.8;
interface ILendingPoolAddressesProvider {
//events
event LendingPoolUpdated(address indexed newAddress);
event LendingPoolManagerUpdated(address indexed newAddress);
event AaveAdminUpdated(address indexed newAddress);
event LendingPoolConfiguratorUpdated(address indexed newAddress);
event LendingPoolLiquidationManagerUpdated(address indexed newAddress);
event LendingPoolCollateralManagerUpdated(address indexed newAddress);
event EthereumAddressUpdated(address indexed newAddress);
event PriceOracleUpdated(address indexed newAddress);
event LendingRateOracleUpdated(address indexed newAddress);
@ -26,13 +26,13 @@ interface ILendingPoolAddressesProvider {
function setLendingPoolConfiguratorImpl(address configurator) external;
function getLendingPoolLiquidationManager() external view returns (address);
function getLendingPoolCollateralManager() external view returns (address);
function setLendingPoolLiquidationManager(address manager) external;
function setLendingPoolCollateralManager(address manager) external;
function getLendingPoolManager() external view returns (address);
function getAaveAdmin() external view returns (address);
function setLendingPoolManager(address lendingPoolManager) external;
function setAaveAdmin(address aaveAdmin) external;
function getPriceOracle() external view returns (address);

View File

@ -21,7 +21,7 @@ import {IStableDebtToken} from '../tokenization/interfaces/IStableDebtToken.sol'
import {IVariableDebtToken} from '../tokenization/interfaces/IVariableDebtToken.sol';
import {IFlashLoanReceiver} from '../flashloan/interfaces/IFlashLoanReceiver.sol';
import {ISwapAdapter} from '../interfaces/ISwapAdapter.sol';
import {LendingPoolLiquidationManager} from './LendingPoolLiquidationManager.sol';
import {LendingPoolCollateralManager} from './LendingPoolCollateralManager.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol';
@ -435,10 +435,10 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
bool receiveAToken
) external override {
whenNotPaused();
address liquidationManager = _addressesProvider.getLendingPoolLiquidationManager();
address collateralManager = _addressesProvider.getLendingPoolCollateralManager();
//solium-disable-next-line
(bool success, bytes memory result) = liquidationManager.delegatecall(
(bool success, bytes memory result) = collateralManager.delegatecall(
abi.encodeWithSignature(
'liquidationCall(address,address,address,uint256,bool)',
collateral,
@ -458,19 +458,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
}
}
struct FlashLoanLocalVars {
uint256 premium;
uint256 amountPlusPremium;
uint256 amountPlusPremiumInETH;
uint256 receiverBalance;
uint256 receiverAllowance;
uint256 availableBalance;
uint256 assetPrice;
IFlashLoanReceiver receiver;
address aTokenAddress;
address oracle;
}
/**
* @dev flashes the underlying collateral on an user to swap for the owed asset and repay
* - Both the owner of the position and other liquidators can execute it
@ -495,10 +482,10 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
require(!_flashLiquidationLocked, Errors.REENTRANCY_NOT_ALLOWED);
_flashLiquidationLocked = true;
address liquidationManager = _addressesProvider.getLendingPoolLiquidationManager();
address collateralManager = _addressesProvider.getLendingPoolCollateralManager();
//solium-disable-next-line
(bool success, bytes memory result) = liquidationManager.delegatecall(
(bool success, bytes memory result) = collateralManager.delegatecall(
abi.encodeWithSignature(
'repayWithCollateral(address,address,address,uint256,address,bytes)',
collateral,
@ -520,6 +507,14 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
_flashLiquidationLocked = false;
}
struct FlashLoanLocalVars {
uint256 premium;
uint256 amountPlusPremium;
IFlashLoanReceiver receiver;
address aTokenAddress;
address oracle;
}
/**
* @dev allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned. NOTE There are security concerns for developers of flashloan receiver contracts
@ -576,7 +571,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
asset,
msg.sender,
msg.sender,
vars.amountPlusPremium.sub(vars.availableBalance),
vars.amountPlusPremium,
mode,
vars.aTokenAddress,
referralCode,
@ -602,10 +597,10 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
bytes calldata params
) external override {
whenNotPaused();
address liquidationManager = _addressesProvider.getLendingPoolLiquidationManager();
address collateralManager = _addressesProvider.getLendingPoolCollateralManager();
//solium-disable-next-line
(bool success, bytes memory result) = liquidationManager.delegatecall(
(bool success, bytes memory result) = collateralManager.delegatecall(
abi.encodeWithSignature(
'swapLiquidity(address,address,address,uint256,bytes)',
receiverAddress,

View File

@ -23,12 +23,13 @@ import {ValidationLogic} from '../libraries/logic/ValidationLogic.sol';
import {LendingPoolStorage} from './LendingPoolStorage.sol';
/**
* @title LendingPoolLiquidationManager contract
* @title LendingPoolCollateralManager contract
* @author Aave
* @notice Implements the liquidation function.
* @dev LendingPoolLiquidationManager inherits Pausable from OpenZeppelin to have the same storage layout as LendingPool
* @notice Implements actions involving management of collateral in the protocol.
* @notice this contract will be ran always through delegatecall
* @dev LendingPoolCollateralManager inherits VersionedInitializable from OpenZeppelin to have the same storage layout as LendingPool
**/
contract LendingPoolLiquidationManager is VersionedInitializable, LendingPoolStorage {
contract LendingPoolCollateralManager is VersionedInitializable, LendingPoolStorage {
using SafeERC20 for IERC20;
using SafeMath for uint256;
using WadRayMath for uint256;
@ -170,7 +171,7 @@ contract LendingPoolLiquidationManager is VersionedInitializable, LendingPoolSto
vars.userVariableDebt
);
if (Errors.LiquidationErrors(vars.errorCode) != Errors.LiquidationErrors.NO_ERROR) {
if (Errors.CollateralManagerErrors(vars.errorCode) != Errors.CollateralManagerErrors.NO_ERROR) {
return (vars.errorCode, vars.errorMsg);
}
@ -213,7 +214,7 @@ contract LendingPoolLiquidationManager is VersionedInitializable, LendingPoolSto
);
if (currentAvailableCollateral < vars.maxCollateralToLiquidate) {
return (
uint256(Errors.LiquidationErrors.NOT_ENOUGH_LIQUIDITY),
uint256(Errors.CollateralManagerErrors.NOT_ENOUGH_LIQUIDITY),
Errors.NOT_ENOUGH_LIQUIDITY_TO_LIQUIDATE
);
}
@ -285,7 +286,7 @@ contract LendingPoolLiquidationManager is VersionedInitializable, LendingPoolSto
receiveAToken
);
return (uint256(Errors.LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
return (uint256(Errors.CollateralManagerErrors.NO_ERROR), Errors.NO_ERRORS);
}
/**
@ -334,7 +335,7 @@ contract LendingPoolLiquidationManager is VersionedInitializable, LendingPoolSto
vars.userVariableDebt
);
if (Errors.LiquidationErrors(vars.errorCode) != Errors.LiquidationErrors.NO_ERROR) {
if (Errors.CollateralManagerErrors(vars.errorCode) != Errors.CollateralManagerErrors.NO_ERROR) {
return (vars.errorCode, vars.errorMsg);
}
@ -430,7 +431,7 @@ contract LendingPoolLiquidationManager is VersionedInitializable, LendingPoolSto
vars.maxCollateralToLiquidate
);
return (uint256(Errors.LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
return (uint256(Errors.CollateralManagerErrors.NO_ERROR), Errors.NO_ERRORS);
}
/**
@ -451,7 +452,6 @@ contract LendingPoolLiquidationManager is VersionedInitializable, LendingPoolSto
ReserveLogic.ReserveData storage fromReserve = _reserves[fromAsset];
ReserveLogic.ReserveData storage toReserve = _reserves[toAsset];
// Usage of a memory struct of vars to avoid "Stack too deep" errors due to local variables
SwapLiquidityLocalVars memory vars;
(vars.errorCode, vars.errorMsg) = ValidationLogic.validateSwapLiquidity(
@ -461,7 +461,7 @@ contract LendingPoolLiquidationManager is VersionedInitializable, LendingPoolSto
toAsset
);
if (Errors.LiquidationErrors(vars.errorCode) != Errors.LiquidationErrors.NO_ERROR) {
if (Errors.CollateralManagerErrors(vars.errorCode) != Errors.CollateralManagerErrors.NO_ERROR) {
return (vars.errorCode, vars.errorMsg);
}
@ -499,6 +499,11 @@ contract LendingPoolLiquidationManager is VersionedInitializable, LendingPoolSto
address(vars.toReserveAToken),
vars.amountToReceive
);
if (vars.toReserveAToken.balanceOf(msg.sender) == 0) {
_usersConfig[msg.sender].setUsingAsCollateral(toReserve.id, true);
}
vars.toReserveAToken.mint(msg.sender, vars.amountToReceive, toReserve.liquidityIndex);
toReserve.updateInterestRates(
toAsset,
@ -518,12 +523,12 @@ contract LendingPoolLiquidationManager is VersionedInitializable, LendingPoolSto
if (vars.healthFactor < GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD) {
return (
uint256(Errors.LiquidationErrors.HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD),
uint256(Errors.CollateralManagerErrors.HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD),
Errors.HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD
);
}
return (uint256(Errors.LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
return (uint256(Errors.CollateralManagerErrors.NO_ERROR), Errors.NO_ERRORS);
}
/**
@ -549,7 +554,6 @@ contract LendingPoolLiquidationManager is VersionedInitializable, LendingPoolSto
uint256 principalAmountNeeded = 0;
IPriceOracleGetter oracle = IPriceOracleGetter(_addressesProvider.getPriceOracle());
// Usage of a memory struct of vars to avoid "Stack too deep" errors due to local variables
AvailableCollateralToLiquidateLocalVars memory vars;
vars.collateralPrice = oracle.getAssetPrice(collateralAddress);

View File

@ -176,11 +176,8 @@ contract LendingPoolConfigurator is VersionedInitializable {
/**
* @dev only the lending pool manager can call functions affected by this modifier
**/
modifier onlyLendingPoolManager {
require(
addressesProvider.getLendingPoolManager() == msg.sender,
Errors.CALLER_NOT_LENDING_POOL_MANAGER
);
modifier onlyAaveAdmin {
require(addressesProvider.getAaveAdmin() == msg.sender, Errors.CALLER_NOT_AAVE_ADMIN);
_;
}
@ -211,7 +208,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
address variableDebtTokenImpl,
uint8 underlyingAssetDecimals,
address interestRateStrategyAddress
) public onlyLendingPoolManager {
) public onlyAaveAdmin {
address aTokenProxyAddress = _initTokenWithProxy(aTokenImpl, underlyingAssetDecimals);
address stableDebtTokenProxyAddress = _initTokenWithProxy(
@ -255,7 +252,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve to be updated
* @param implementation the address of the new aToken implementation
**/
function updateAToken(address asset, address implementation) external onlyLendingPoolManager {
function updateAToken(address asset, address implementation) external onlyAaveAdmin {
(address aTokenAddress, , ) = pool.getReserveTokensAddresses(asset);
_upgradeTokenImplementation(asset, aTokenAddress, implementation);
@ -268,10 +265,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve to be updated
* @param implementation the address of the new aToken implementation
**/
function updateStableDebtToken(address asset, address implementation)
external
onlyLendingPoolManager
{
function updateStableDebtToken(address asset, address implementation) external onlyAaveAdmin {
(, address stableDebtToken, ) = pool.getReserveTokensAddresses(asset);
_upgradeTokenImplementation(asset, stableDebtToken, implementation);
@ -284,10 +278,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve to be updated
* @param implementation the address of the new aToken implementation
**/
function updateVariableDebtToken(address asset, address implementation)
external
onlyLendingPoolManager
{
function updateVariableDebtToken(address asset, address implementation) external onlyAaveAdmin {
(, , address variableDebtToken) = pool.getReserveTokensAddresses(asset);
_upgradeTokenImplementation(asset, variableDebtToken, implementation);
@ -302,7 +293,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
**/
function enableBorrowingOnReserve(address asset, bool stableBorrowRateEnabled)
external
onlyLendingPoolManager
onlyAaveAdmin
{
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
@ -318,7 +309,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @dev disables borrowing on a reserve
* @param asset the address of the reserve
**/
function disableBorrowingOnReserve(address asset) external onlyLendingPoolManager {
function disableBorrowingOnReserve(address asset) external onlyAaveAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
currentConfig.setBorrowingEnabled(false);
@ -339,7 +330,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus
) external onlyLendingPoolManager {
) external onlyAaveAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
currentConfig.setLtv(ltv);
@ -355,7 +346,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @dev disables a reserve as collateral
* @param asset the address of the reserve
**/
function disableReserveAsCollateral(address asset) external onlyLendingPoolManager {
function disableReserveAsCollateral(address asset) external onlyAaveAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
currentConfig.setLtv(0);
@ -369,7 +360,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @dev enable stable rate borrowing on a reserve
* @param asset the address of the reserve
**/
function enableReserveStableRate(address asset) external onlyLendingPoolManager {
function enableReserveStableRate(address asset) external onlyAaveAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
currentConfig.setStableRateBorrowingEnabled(true);
@ -383,7 +374,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @dev disable stable rate borrowing on a reserve
* @param asset the address of the reserve
**/
function disableReserveStableRate(address asset) external onlyLendingPoolManager {
function disableReserveStableRate(address asset) external onlyAaveAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
currentConfig.setStableRateBorrowingEnabled(false);
@ -397,7 +388,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @dev activates a reserve
* @param asset the address of the reserve
**/
function activateReserve(address asset) external onlyLendingPoolManager {
function activateReserve(address asset) external onlyAaveAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
currentConfig.setActive(true);
@ -411,7 +402,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @dev deactivates a reserve
* @param asset the address of the reserve
**/
function deactivateReserve(address asset) external onlyLendingPoolManager {
function deactivateReserve(address asset) external onlyAaveAdmin {
(
uint256 availableLiquidity,
uint256 totalBorrowsStable,
@ -442,7 +433,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @dev freezes a reserve. A freezed reserve doesn't accept any new deposit, borrow or rate swap, but can accept repayments, liquidations, rate rebalances and redeems
* @param asset the address of the reserve
**/
function freezeReserve(address asset) external onlyLendingPoolManager {
function freezeReserve(address asset) external onlyAaveAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
currentConfig.setFrozen(true);
@ -456,7 +447,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @dev unfreezes a reserve
* @param asset the address of the reserve
**/
function unfreezeReserve(address asset) external onlyLendingPoolManager {
function unfreezeReserve(address asset) external onlyAaveAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
currentConfig.setFrozen(false);
@ -471,7 +462,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve
* @param ltv the new value for the loan to value
**/
function setLtv(address asset, uint256 ltv) external onlyLendingPoolManager {
function setLtv(address asset, uint256 ltv) external onlyAaveAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
currentConfig.setLtv(ltv);
@ -486,10 +477,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve
* @param threshold the new value for the liquidation threshold
**/
function setLiquidationThreshold(address asset, uint256 threshold)
external
onlyLendingPoolManager
{
function setLiquidationThreshold(address asset, uint256 threshold) external onlyAaveAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
currentConfig.setLiquidationThreshold(threshold);
@ -504,7 +492,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve
* @param bonus the new value for the liquidation bonus
**/
function setLiquidationBonus(address asset, uint256 bonus) external onlyLendingPoolManager {
function setLiquidationBonus(address asset, uint256 bonus) external onlyAaveAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
currentConfig.setLiquidationBonus(bonus);
@ -519,7 +507,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param asset the address of the reserve
* @param decimals the new number of decimals
**/
function setReserveDecimals(address asset, uint256 decimals) external onlyLendingPoolManager {
function setReserveDecimals(address asset, uint256 decimals) external onlyAaveAdmin {
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
currentConfig.setDecimals(decimals);
@ -536,7 +524,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
**/
function setReserveInterestRateStrategyAddress(address asset, address rateStrategyAddress)
external
onlyLendingPoolManager
onlyAaveAdmin
{
pool.setReserveInterestRateStrategyAddress(asset, rateStrategyAddress);
emit ReserveInterestRateStrategyChanged(asset, rateStrategyAddress);
@ -587,7 +575,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @dev pauses or unpauses LendingPool actions
* @param val the boolean value to set the current pause state of LendingPool
**/
function setPoolPause(bool val) external onlyLendingPoolManager {
function setPoolPause(bool val) external onlyAaveAdmin {
pool.setPause(val);
}
}

View File

@ -59,13 +59,13 @@ library Errors {
string public constant STABLE_BORROW_RATE_OVERFLOW = '51'; // Stable borrow rate overflows uint128
//require error messages - LendingPoolConfiguration
string public constant CALLER_NOT_LENDING_POOL_MANAGER = '35'; // 'The caller must be a lending pool manager'
string public constant CALLER_NOT_AAVE_ADMIN = '35'; // 'The caller must be the aave admin'
string public constant RESERVE_LIQUIDITY_NOT_0 = '36'; // 'The liquidity of the reserve needs to be 0'
//require error messages - LendingPoolAddressesProviderRegistry
string public constant PROVIDER_NOT_REGISTERED = '37'; // 'Provider is not registered'
//return error messages - LendingPoolLiquidationManager
//return error messages - LendingPoolCollateralManager
string public constant HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '38'; // 'Health factor is not below the threshold'
string public constant COLLATERAL_CANNOT_BE_LIQUIDATED = '39'; // 'The collateral chosen cannot be liquidated'
string public constant SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER = '40'; // 'User did not borrow the specified currency'
@ -79,7 +79,7 @@ library Errors {
// pausable error message
string public constant IS_PAUSED = '58'; // 'Pool is paused'
enum LiquidationErrors {
enum CollateralManagerErrors {
NO_ERROR,
NO_COLLATERAL_AVAILABLE,
COLLATERAL_CANNOT_BE_LIQUIDATED,
@ -88,6 +88,7 @@ library Errors {
NOT_ENOUGH_LIQUIDITY,
NO_ACTIVE_RESERVE,
HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD,
INVALID_EQUAL_ASSETS_TO_SWAP
INVALID_EQUAL_ASSETS_TO_SWAP,
NO_UNFREEZED_RESERVE
}
}

View File

@ -69,7 +69,6 @@ library GenericLogic {
return true;
}
// Usage of a memory struct of vars to avoid "Stack too deep" errors due to local variables
balanceDecreaseAllowedLocalVars memory vars;
(vars.ltv, , , vars.decimals) = reservesData[asset].configuration.getParams();

View File

@ -351,12 +351,12 @@ library ValidationLogic {
if (
!collateralReserve.configuration.getActive() || !principalReserve.configuration.getActive()
) {
return (uint256(Errors.LiquidationErrors.NO_ACTIVE_RESERVE), Errors.NO_ACTIVE_RESERVE);
return (uint256(Errors.CollateralManagerErrors.NO_ACTIVE_RESERVE), Errors.NO_ACTIVE_RESERVE);
}
if (userHealthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD) {
return (
uint256(Errors.LiquidationErrors.HEALTH_FACTOR_ABOVE_THRESHOLD),
uint256(Errors.CollateralManagerErrors.HEALTH_FACTOR_ABOVE_THRESHOLD),
Errors.HEALTH_FACTOR_NOT_BELOW_THRESHOLD
);
}
@ -367,19 +367,19 @@ library ValidationLogic {
//if collateral isn't enabled as collateral by user, it cannot be liquidated
if (!isCollateralEnabled) {
return (
uint256(Errors.LiquidationErrors.COLLATERAL_CANNOT_BE_LIQUIDATED),
uint256(Errors.CollateralManagerErrors.COLLATERAL_CANNOT_BE_LIQUIDATED),
Errors.COLLATERAL_CANNOT_BE_LIQUIDATED
);
}
if (userStableDebt == 0 && userVariableDebt == 0) {
return (
uint256(Errors.LiquidationErrors.CURRRENCY_NOT_BORROWED),
uint256(Errors.CollateralManagerErrors.CURRRENCY_NOT_BORROWED),
Errors.SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER
);
}
return (uint256(Errors.LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
return (uint256(Errors.CollateralManagerErrors.NO_ERROR), Errors.NO_ERRORS);
}
/**
@ -404,14 +404,14 @@ library ValidationLogic {
if (
!collateralReserve.configuration.getActive() || !principalReserve.configuration.getActive()
) {
return (uint256(Errors.LiquidationErrors.NO_ACTIVE_RESERVE), Errors.NO_ACTIVE_RESERVE);
return (uint256(Errors.CollateralManagerErrors.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),
uint256(Errors.CollateralManagerErrors.HEALTH_FACTOR_ABOVE_THRESHOLD),
Errors.HEALTH_FACTOR_NOT_BELOW_THRESHOLD
);
}
@ -423,7 +423,7 @@ library ValidationLogic {
//if collateral isn't enabled as collateral by user, it cannot be liquidated
if (!isCollateralEnabled) {
return (
uint256(Errors.LiquidationErrors.COLLATERAL_CANNOT_BE_LIQUIDATED),
uint256(Errors.CollateralManagerErrors.COLLATERAL_CANNOT_BE_LIQUIDATED),
Errors.COLLATERAL_CANNOT_BE_LIQUIDATED
);
}
@ -431,12 +431,12 @@ library ValidationLogic {
if (userStableDebt == 0 && userVariableDebt == 0) {
return (
uint256(Errors.LiquidationErrors.CURRRENCY_NOT_BORROWED),
uint256(Errors.CollateralManagerErrors.CURRRENCY_NOT_BORROWED),
Errors.SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER
);
}
return (uint256(Errors.LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
return (uint256(Errors.CollateralManagerErrors.NO_ERROR), Errors.NO_ERRORS);
}
/**
@ -452,17 +452,24 @@ library ValidationLogic {
address fromAsset,
address toAsset
) internal view returns (uint256, string memory) {
if (!fromReserve.configuration.getActive() || !toReserve.configuration.getActive()) {
return (uint256(Errors.LiquidationErrors.NO_ACTIVE_RESERVE), Errors.NO_ACTIVE_RESERVE);
}
if (fromAsset == toAsset) {
return (
uint256(Errors.LiquidationErrors.INVALID_EQUAL_ASSETS_TO_SWAP),
uint256(Errors.CollateralManagerErrors.INVALID_EQUAL_ASSETS_TO_SWAP),
Errors.INVALID_EQUAL_ASSETS_TO_SWAP
);
}
return (uint256(Errors.LiquidationErrors.NO_ERROR), Errors.NO_ERRORS);
(bool isToActive, bool isToFreezed, , ) = toReserve.configuration.getFlags();
if (!fromReserve.configuration.getActive() || !isToActive) {
return (uint256(Errors.CollateralManagerErrors.NO_ACTIVE_RESERVE), Errors.NO_ACTIVE_RESERVE);
}
if (isToFreezed) {
return (
uint256(Errors.CollateralManagerErrors.NO_UNFREEZED_RESERVE),
Errors.NO_UNFREEZED_RESERVE
);
}
return (uint256(Errors.CollateralManagerErrors.NO_ERROR), Errors.NO_ERRORS);
}
}

View File

@ -9,8 +9,9 @@ contract MockAToken is AToken {
LendingPool _pool,
address _underlyingAssetAddress,
string memory _tokenName,
string memory _tokenSymbol
) public AToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol) {}
string memory _tokenSymbol,
address incentivesController
) public AToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol, incentivesController) {}
function getRevision() internal override pure returns (uint256) {
return 0x2;

View File

@ -9,8 +9,12 @@ contract MockStableDebtToken is StableDebtToken {
address _pool,
address _underlyingAssetAddress,
string memory _tokenName,
string memory _tokenSymbol
) public StableDebtToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol) {}
string memory _tokenSymbol,
address incentivesController
)
public
StableDebtToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol, incentivesController)
{}
function getRevision() internal override pure returns (uint256) {
return 0x2;

View File

@ -9,8 +9,18 @@ contract MockVariableDebtToken is VariableDebtToken {
address _pool,
address _underlyingAssetAddress,
string memory _tokenName,
string memory _tokenSymbol
) public VariableDebtToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol) {}
string memory _tokenSymbol,
address incentivesController
)
public
VariableDebtToken(
_pool,
_underlyingAssetAddress,
_tokenName,
_tokenSymbol,
incentivesController
)
{}
function getRevision() internal override pure returns (uint256) {
return 0x2;

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
import {ERC20} from './ERC20.sol';
import {IncentivizedERC20} from './IncentivizedERC20.sol';
import {LendingPool} from '../lendingpool/LendingPool.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
@ -18,9 +18,9 @@ import {SafeERC20} from '../misc/SafeERC20.sol';
* @dev Implementation of the interest bearing token for the DLP protocol.
* @author Aave
*/
contract AToken is VersionedInitializable, ERC20, IAToken {
contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
using WadRayMath for uint256;
using SafeERC20 for ERC20;
using SafeERC20 for IncentivizedERC20;
uint256 public constant UINT_MAX_VALUE = uint256(-1);
address public immutable UNDERLYING_ASSET_ADDRESS;
@ -49,8 +49,9 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
LendingPool pool,
address underlyingAssetAddress,
string memory tokenName,
string memory tokenSymbol
) public ERC20(tokenName, tokenSymbol, 18) {
string memory tokenSymbol,
address incentivesController
) public IncentivizedERC20(tokenName, tokenSymbol, 18, incentivesController) {
POOL = pool;
UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress;
}
@ -106,7 +107,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
_burn(user, scaledAmount);
//transfers the underlying to the target
ERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(receiverOfUnderlying, amount);
IncentivizedERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(receiverOfUnderlying, amount);
//transfer event to track balances
emit Transfer(user, address(0), amount);
@ -158,7 +159,12 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
* @param user the user for which the balance is being calculated
* @return the total balance of the user
**/
function balanceOf(address user) public override(ERC20, IERC20) view returns (uint256) {
function balanceOf(address user)
public
override(IncentivizedERC20, IERC20)
view
returns (uint256)
{
return super.balanceOf(user).rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS));
}
@ -172,13 +178,28 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
return super.balanceOf(user);
}
/**
* @dev returns the principal balance of the user and principal total supply.
* @param user the address of the user
* @return the principal balance of the user
* @return the principal total supply
**/
function getScaledUserBalanceAndSupply(address user)
external
override
view
returns (uint256, uint256)
{
return (super.balanceOf(user), super.totalSupply());
}
/**
* @dev calculates the total supply of the specific aToken
* since the balance of every single user increases over time, the total supply
* does that too.
* @return the current total supply
**/
function totalSupply() public override(ERC20, IERC20) view returns (uint256) {
function totalSupply() public override(IncentivizedERC20, IERC20) view returns (uint256) {
uint256 currentSupplyScaled = super.totalSupply();
if (currentSupplyScaled == 0) {
@ -211,7 +232,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
onlyLendingPool
returns (uint256)
{
ERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(target, amount);
IncentivizedERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(target, amount);
return amount;
}

View File

@ -5,16 +5,20 @@ import {Context} from '../misc/Context.sol';
import {IERC20} from '../interfaces/IERC20.sol';
import {IERC20Detailed} from '../interfaces/IERC20Detailed.sol';
import {SafeMath} from '../libraries/math/SafeMath.sol';
import {IAaveIncentivesController} from '../interfaces/IAaveIncentivesController.sol';
/**
* @title ERC20
* @notice Basic ERC20 implementation
* @author Aave, inspired by the Openzeppelin ERC20 implementation
**/
contract ERC20 is Context, IERC20, IERC20Detailed {
contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
using SafeMath for uint256;
IAaveIncentivesController internal immutable _incentivesController;
mapping(address => uint256) internal _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 internal _totalSupply;
string private _name;
@ -24,11 +28,13 @@ contract ERC20 is Context, IERC20, IERC20Detailed {
constructor(
string memory name,
string memory symbol,
uint8 decimals
uint8 decimals,
address incentivesController
) public {
_name = name;
_symbol = symbol;
_decimals = decimals;
_incentivesController = IAaveIncentivesController(incentivesController);
}
/**
@ -169,8 +175,18 @@ contract ERC20 is Context, IERC20, IERC20Detailed {
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, 'ERC20: transfer amount exceeds balance');
uint256 oldSenderBalance = _balances[sender];
_balances[sender] = oldSenderBalance.sub(amount, 'ERC20: transfer amount exceeds balance');
uint256 oldRecipientBalance = _balances[recipient];
_balances[recipient] = _balances[recipient].add(amount);
if (address(_incentivesController) != address(0)) {
uint256 totalSupply = _totalSupply;
_incentivesController.handleAction(sender, totalSupply, oldSenderBalance);
if (sender != recipient) {
_incentivesController.handleAction(recipient, totalSupply, oldRecipientBalance);
}
}
}
function _mint(address account, uint256 amount) internal virtual {
@ -178,8 +194,15 @@ contract ERC20 is Context, IERC20, IERC20Detailed {
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
uint256 oldTotalSupply = _totalSupply;
_totalSupply = oldTotalSupply.add(amount);
uint256 oldAccountBalance = _balances[account];
_balances[account] = oldAccountBalance.add(amount);
if (address(_incentivesController) != address(0)) {
_incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance);
}
}
function _burn(address account, uint256 amount) internal virtual {
@ -187,8 +210,15 @@ contract ERC20 is Context, IERC20, IERC20Detailed {
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, 'ERC20: burn amount exceeds balance');
_totalSupply = _totalSupply.sub(amount);
uint256 oldTotalSupply = _totalSupply;
_totalSupply = oldTotalSupply.sub(amount);
uint256 oldAccountBalance = _balances[account];
_balances[account] = oldAccountBalance.sub(amount, 'ERC20: burn amount exceeds balance');
if (address(_incentivesController) != address(0)) {
_incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance);
}
}
function _approve(

View File

@ -26,8 +26,9 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
address pool,
address underlyingAsset,
string memory name,
string memory symbol
) public DebtTokenBase(pool, underlyingAsset, name, symbol) {}
string memory symbol,
address incentivesController
) public DebtTokenBase(pool, underlyingAsset, name, symbol, incentivesController) {}
/**
* @dev gets the revision of the stable debt token implementation

View File

@ -22,8 +22,9 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
address pool,
address underlyingAsset,
string memory name,
string memory symbol
) public DebtTokenBase(pool, underlyingAsset, name, symbol) {}
string memory symbol,
address incentivesController
) public DebtTokenBase(pool, underlyingAsset, name, symbol, incentivesController) {}
/**
* @dev gets the revision of the stable debt token implementation

View File

@ -8,7 +8,7 @@ import {ILendingPool} from '../../interfaces/ILendingPool.sol';
import {
VersionedInitializable
} from '../../libraries/openzeppelin-upgradeability/VersionedInitializable.sol';
import {ERC20} from '../ERC20.sol';
import {IncentivizedERC20} from '../IncentivizedERC20.sol';
import {Errors} from '../../libraries/helpers/Errors.sol';
/**
@ -17,7 +17,7 @@ import {Errors} from '../../libraries/helpers/Errors.sol';
* @author Aave
*/
abstract contract DebtTokenBase is ERC20, VersionedInitializable {
abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
address internal immutable UNDERLYING_ASSET;
ILendingPool internal immutable POOL;
mapping(address => uint256) internal _usersData;
@ -38,8 +38,9 @@ abstract contract DebtTokenBase is ERC20, VersionedInitializable {
address pool,
address underlyingAssetAddress,
string memory name,
string memory symbol
) public ERC20(name, symbol, 18) {
string memory symbol,
address incentivesController
) public IncentivizedERC20(name, symbol, 18, incentivesController) {
POOL = ILendingPool(pool);
UNDERLYING_ASSET = underlyingAssetAddress;
}

View File

@ -82,6 +82,14 @@ interface IAToken is IERC20 {
**/
function scaledBalanceOf(address user) external view returns (uint256);
/**
* @dev returns the principal balance of the user and principal total supply.
* @param user the address of the user
* @return the principal balance of the user
* @return the principal total supply
**/
function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);
/**
* @dev Used to validate transfers before actually executing them.
* @param user address of the user to check

View File

@ -0,0 +1,3 @@
export const TEST_SNAPSHOT_ID = '0x1';
export const BUIDLEREVM_CHAINID = 31337;
export const COVERAGE_CHAINID = 1337;

View File

@ -1,22 +1,17 @@
import {
iAssetBase,
iAavePoolAssets,
IMarketRates,
iAssetAggregatorBase,
AavePools,
eEthereumNetwork,
iAavePoolAssets,
iAssetAggregatorBase,
iAssetBase,
iBasicDistributionParams,
IMarketRates,
iMultiPoolsAssets,
IReserveParams,
tEthereumAddress,
iBasicDistributionParams,
eEthereumNetwork,
} from './types';
import BigNumber from 'bignumber.js';
import {getParamPerPool, getParamPerNetwork} from './contracts-helpers';
export const TEST_SNAPSHOT_ID = '0x1';
export const BUIDLEREVM_CHAINID = 31337;
export const COVERAGE_CHAINID = 1337;
import {getParamPerNetwork, getParamPerPool} from './contracts-helpers';
// ----------------
// MATH

View File

@ -21,7 +21,7 @@ import {PriceOracle} from '../types/PriceOracle';
import {MockAggregator} from '../types/MockAggregator';
import {LendingRateOracle} from '../types/LendingRateOracle';
import {DefaultReserveInterestRateStrategy} from '../types/DefaultReserveInterestRateStrategy';
import {LendingPoolLiquidationManager} from '../types/LendingPoolLiquidationManager';
import {LendingPoolCollateralManager} from '../types/LendingPoolCollateralManager';
import {InitializableAdminUpgradeabilityProxy} from '../types/InitializableAdminUpgradeabilityProxy';
import {MockFlashLoanReceiver} from '../types/MockFlashLoanReceiver';
import {WalletBalanceProvider} from '../types/WalletBalanceProvider';
@ -192,16 +192,16 @@ export const deployChainlinkProxyPriceProvider = async ([
export const deployLendingRateOracle = async () =>
await deployContract<LendingRateOracle>(eContractid.LendingRateOracle, []);
export const deployLendingPoolLiquidationManager = async () => {
const liquidationManagerArtifact = await readArtifact(
export const deployLendingPoolCollateralManager = async () => {
const collateralManagerArtifact = await readArtifact(
BRE.config.paths.artifacts,
eContractid.LendingPoolLiquidationManager
eContractid.LendingPoolCollateralManager
);
const factory = await linkLibrariesToArtifact(liquidationManagerArtifact);
const factory = await linkLibrariesToArtifact(collateralManagerArtifact);
const liquidationManager = await factory.deploy();
return (await liquidationManager.deployed()) as LendingPoolLiquidationManager;
const collateralManager = await factory.deploy();
return (await collateralManager.deployed()) as LendingPoolCollateralManager;
};
export const deployInitializableAdminUpgradeabilityProxy = async () =>
@ -251,49 +251,55 @@ export const deployDefaultReserveInterestRateStrategy = async ([
]
);
export const deployStableDebtToken = async ([name, symbol, underlyingAsset, poolAddress]: [
string,
string,
tEthereumAddress,
tEthereumAddress
]) => {
export const deployStableDebtToken = async ([
name,
symbol,
underlyingAsset,
poolAddress,
incentivesController,
]: [string, string, tEthereumAddress, tEthereumAddress, tEthereumAddress]) => {
const token = await deployContract<StableDebtToken>(eContractid.StableDebtToken, [
poolAddress,
underlyingAsset,
name,
symbol,
incentivesController,
]);
return token;
};
export const deployVariableDebtToken = async ([name, symbol, underlyingAsset, poolAddress]: [
string,
string,
tEthereumAddress,
tEthereumAddress
]) => {
export const deployVariableDebtToken = async ([
name,
symbol,
underlyingAsset,
poolAddress,
incentivesController,
]: [string, string, tEthereumAddress, tEthereumAddress, tEthereumAddress]) => {
const token = await deployContract<VariableDebtToken>(eContractid.VariableDebtToken, [
poolAddress,
underlyingAsset,
name,
symbol,
incentivesController,
]);
return token;
};
export const deployGenericAToken = async ([poolAddress, underlyingAssetAddress, name, symbol]: [
tEthereumAddress,
tEthereumAddress,
string,
string
]) => {
export const deployGenericAToken = async ([
poolAddress,
underlyingAssetAddress,
name,
symbol,
incentivesController,
]: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress]) => {
const token = await deployContract<AToken>(eContractid.AToken, [
poolAddress,
underlyingAssetAddress,
name,
symbol,
incentivesController,
]);
return token;

View File

@ -30,7 +30,7 @@ export enum eContractid {
LendingRateOracle = 'LendingRateOracle',
ChainlinkProxyPriceProvider = 'ChainlinkProxyPriceProvider',
DefaultReserveInterestRateStrategy = 'DefaultReserveInterestRateStrategy',
LendingPoolLiquidationManager = 'LendingPoolLiquidationManager',
LendingPoolCollateralManager = 'LendingPoolCollateralManager',
InitializableAdminUpgradeabilityProxy = 'InitializableAdminUpgradeabilityProxy',
MockFlashLoanReceiver = 'MockFlashLoanReceiver',
MockSwapAdapter = 'MockSwapAdapter',
@ -67,6 +67,7 @@ export enum ProtocolErrors {
NO_VARIABLE_RATE_LOAN_IN_RESERVE = '18', // 'User does not have a variable rate loan in progress on this reserve'
UNDERLYING_BALANCE_NOT_GREATER_THAN_0 = '19', // 'The underlying balance needs to be greater than 0'
DEPOSIT_ALREADY_IN_USE = '20', // 'User deposit is already being used as collateral'
INVALID_EQUAL_ASSETS_TO_SWAP = '56', // User can't use same reserve as destination of liquidity swap
// require error messages - LendingPool
NOT_ENOUGH_STABLE_BORROW_BALANCE = '21', // 'User does not have any stable rate loan for this reserve'
@ -86,13 +87,13 @@ export enum ProtocolErrors {
RESERVE_ALREADY_INITIALIZED = '34', // 'Reserve has already been initialized'
//require error messages - LendingPoolConfiguration
CALLER_NOT_LENDING_POOL_MANAGER = '35', // 'The caller must be a lending pool manager'
CALLER_NOT_AAVE_ADMIN = '35', // 'The caller must be the aave admin'
RESERVE_LIQUIDITY_NOT_0 = '36', // 'The liquidity of the reserve needs to be 0'
//require error messages - LendingPoolAddressesProviderRegistry
PROVIDER_NOT_REGISTERED = '37', // 'Provider is not registered'
//return error messages - LendingPoolLiquidationManager
//return error messages - LendingPoolCollateralManager
HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '38', // 'Health factor is not below the threshold'
COLLATERAL_CANNOT_BE_LIQUIDATED = '39', // 'The collateral chosen cannot be liquidated'
SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER = '40', // 'User did not borrow the specified currency'

10836
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@ import {
deployChainlinkProxyPriceProvider,
deployLendingRateOracle,
deployDefaultReserveInterestRateStrategy,
deployLendingPoolLiquidationManager,
deployLendingPoolCollateralManager,
deployMockFlashLoanReceiver,
deployWalletBalancerProvider,
getLendingPool,
@ -175,7 +175,8 @@ const initReserves = async (
lendingPoolAddressesProvider: LendingPoolAddressesProvider,
lendingPool: LendingPool,
lendingPoolConfigurator: LendingPoolConfigurator,
aavePool: AavePools
aavePool: AavePools,
incentivesController: tEthereumAddress
) => {
if (aavePool !== AavePools.proto && aavePool !== AavePools.secondary) {
console.log(`Invalid Aave pool ${aavePool}`);
@ -230,6 +231,7 @@ const initReserves = async (
`stableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
tokenAddress,
lendingPool.address,
incentivesController,
]);
const variableDebtToken = await deployVariableDebtToken([
@ -237,6 +239,7 @@ const initReserves = async (
`variableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
tokenAddress,
lendingPool.address,
incentivesController,
]);
const aToken = await deployGenericAToken([
@ -244,6 +247,7 @@ const initReserves = async (
tokenAddress,
`Aave interest bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
`a${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
incentivesController,
]);
if (process.env.POOL === AavePools.secondary) {
@ -349,12 +353,12 @@ export const waitForTx = async (tx: ContractTransaction) => await tx.wait();
const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
console.time('setup');
const lendingPoolManager = await deployer.getAddress();
const aaveAdmin = await deployer.getAddress();
const mockTokens = await deployAllMockTokens(deployer);
const addressesProvider = await deployLendingPoolAddressesProvider();
await waitForTx(await addressesProvider.setLendingPoolManager(lendingPoolManager));
await waitForTx(await addressesProvider.setAaveAdmin(aaveAdmin));
const addressesProviderRegistry = await deployLendingPoolAddressesProviderRegistry();
await waitForTx(
@ -481,7 +485,8 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
addressesProvider,
lendingPoolProxy,
lendingPoolConfiguratorProxy,
AavePools.proto
AavePools.proto,
ZERO_ADDRESS
);
await enableReservesToBorrow(
reservesParams,
@ -496,9 +501,9 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
lendingPoolConfiguratorProxy
);
const liquidationManager = await deployLendingPoolLiquidationManager();
const collateralManager = await deployLendingPoolCollateralManager();
await waitForTx(
await addressesProvider.setLendingPoolLiquidationManager(liquidationManager.address)
await addressesProvider.setLendingPoolCollateralManager(collateralManager.address)
);
const mockFlashLoanReceiver = await deployMockFlashLoanReceiver(addressesProvider.address);

View File

@ -2,7 +2,6 @@ import {
MAX_UINT_AMOUNT,
ZERO_ADDRESS,
getATokenDomainSeparatorPerNetwork,
BUIDLEREVM_CHAINID,
} from '../helpers/constants';
import {buildPermitParams, getSignatureFromTypedData} from '../helpers/contracts-helpers';
import {expect} from 'chai';
@ -11,6 +10,7 @@ import {eEthereumNetwork} from '../helpers/types';
import {makeSuite, TestEnv} from './helpers/make-suite';
import {BRE} from '../helpers/misc-utils';
import {waitForTx} from './__setup.spec';
import {BUIDLEREVM_CHAINID} from '../helpers/buidler-constants';
const {parseEther} = ethers.utils;

View File

@ -13,12 +13,63 @@ const {expect} = require('chai');
makeSuite('LendingPool SwapDeposit function', (testEnv: TestEnv) => {
let _mockSwapAdapter = {} as MockSwapAdapter;
const {HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD} = ProtocolErrors;
const {
HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD,
NO_UNFREEZED_RESERVE,
NO_ACTIVE_RESERVE,
INVALID_EQUAL_ASSETS_TO_SWAP,
} = ProtocolErrors;
before(async () => {
_mockSwapAdapter = await getMockSwapAdapter();
});
it('Should not allow to swap if from equal to', async () => {
const {pool, weth} = testEnv;
await expect(
pool.swapLiquidity(
_mockSwapAdapter.address,
weth.address,
weth.address,
'1'.toString(),
'0x10'
)
).to.be.revertedWith(INVALID_EQUAL_ASSETS_TO_SWAP);
});
it('Should not allow to swap if from or to reserves are not active', async () => {
const {pool, weth, dai, configurator} = testEnv;
await configurator.deactivateReserve(weth.address);
await expect(
pool.swapLiquidity(
_mockSwapAdapter.address,
weth.address,
dai.address,
'1'.toString(),
'0x10'
)
).to.be.revertedWith(NO_ACTIVE_RESERVE);
await configurator.activateReserve(weth.address);
await configurator.deactivateReserve(dai.address);
await expect(
pool.swapLiquidity(
_mockSwapAdapter.address,
weth.address,
dai.address,
'1'.toString(),
'0x10'
)
).to.be.revertedWith(NO_ACTIVE_RESERVE);
//cleanup state
await configurator.activateReserve(dai.address);
});
it('Deposits WETH into the reserve', async () => {
const {pool, weth, users} = testEnv;
const amountToDeposit = ethers.utils.parseEther('1');
@ -32,6 +83,7 @@ makeSuite('LendingPool SwapDeposit function', (testEnv: TestEnv) => {
.deposit(weth.address, amountToDeposit, await signer.getAddress(), '0');
}
});
it('User tries to swap more then he can, revert expected', async () => {
const {pool, weth, dai} = testEnv;
await expect(
@ -45,19 +97,6 @@ makeSuite('LendingPool SwapDeposit function', (testEnv: TestEnv) => {
).to.be.revertedWith('55');
});
it('User tries to swap asset on equal asset, revert expected', async () => {
const {pool, weth} = testEnv;
await expect(
pool.swapLiquidity(
_mockSwapAdapter.address,
weth.address,
weth.address,
ethers.utils.parseEther('0.1'),
'0x10'
)
).to.be.revertedWith('56');
});
it('User tries to swap more then available on the reserve', async () => {
const {pool, weth, dai, users, aEth, deployer} = testEnv;
@ -134,6 +173,9 @@ makeSuite('LendingPool SwapDeposit function', (testEnv: TestEnv) => {
reserveBalanceDAIBefore.add(amountToReturn).toString(),
'was received incorrect amount if reserve funds'
);
expect(
(await pool.getUserReserveData(dai.address, userAddress)).usageAsCollateralEnabled
).to.be.equal(true, 'usage as collateral was not enabled on destination reserve for the user');
});
it('User tries to drop HF below one', async () => {
@ -151,7 +193,7 @@ makeSuite('LendingPool SwapDeposit function', (testEnv: TestEnv) => {
});
it('Should set usage as collateral to false if no leftovers after swap', async () => {
const {pool, weth, dai, aEth, users} = testEnv;
const {pool, weth, dai, users} = testEnv;
const userAddress = await pool.signer.getAddress();
// add more liquidity to allow user 0 to swap everything he has
@ -195,4 +237,22 @@ makeSuite('LendingPool SwapDeposit function', (testEnv: TestEnv) => {
'usageAsCollateralEnabled are not set to false'
);
});
it('Should not allow to swap if to reserve are freezed', async () => {
const {pool, weth, dai, configurator} = testEnv;
await configurator.freezeReserve(dai.address);
await expect(
pool.swapLiquidity(
_mockSwapAdapter.address,
weth.address,
dai.address,
'1'.toString(),
'0x10'
)
).to.be.revertedWith(NO_UNFREEZED_RESERVE);
//cleanup state
await configurator.unfreezeReserve(dai.address);
});
});

View File

@ -6,7 +6,7 @@ import {ProtocolErrors} from '../helpers/types';
const {expect} = require('chai');
makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
const {CALLER_NOT_LENDING_POOL_MANAGER, RESERVE_LIQUIDITY_NOT_0} = ProtocolErrors;
const {CALLER_NOT_AAVE_ADMIN, RESERVE_LIQUIDITY_NOT_0} = ProtocolErrors;
it('Deactivates the ETH reserve', async () => {
const {configurator, pool, weth} = testEnv;
@ -23,20 +23,20 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(isActive).to.be.equal(true);
});
it('Check the onlyLendingPoolManager on deactivateReserve ', async () => {
it('Check the onlyAaveAdmin on deactivateReserve ', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).deactivateReserve(weth.address),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Check the onlyLendingPoolManager on activateReserve ', async () => {
it('Check the onlyAaveAdmin on activateReserve ', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).activateReserve(weth.address),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Freezes the ETH reserve', async () => {
@ -54,20 +54,20 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(isFreezed).to.be.equal(false);
});
it('Check the onlyLendingPoolManager on freezeReserve ', async () => {
it('Check the onlyAaveAdmin on freezeReserve ', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).freezeReserve(weth.address),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Check the onlyLendingPoolManager on unfreezeReserve ', async () => {
it('Check the onlyAaveAdmin on unfreezeReserve ', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).unfreezeReserve(weth.address),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Deactivates the ETH reserve for borrowing', async () => {
@ -86,20 +86,20 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(variableBorrowIndex.toString()).to.be.equal(RAY);
});
it('Check the onlyLendingPoolManager on disableBorrowingOnReserve ', async () => {
it('Check the onlyAaveAdmin on disableBorrowingOnReserve ', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).disableBorrowingOnReserve(weth.address),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Check the onlyLendingPoolManager on enableBorrowingOnReserve ', async () => {
it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, true),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Deactivates the ETH reserve as collateral', async () => {
@ -117,22 +117,22 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(usageAsCollateralEnabled).to.be.equal(true);
});
it('Check the onlyLendingPoolManager on disableReserveAsCollateral ', async () => {
it('Check the onlyAaveAdmin on disableReserveAsCollateral ', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).disableReserveAsCollateral(weth.address),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Check the onlyLendingPoolManager on enableReserveAsCollateral ', async () => {
it('Check the onlyAaveAdmin on enableReserveAsCollateral ', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator
.connect(users[2].signer)
.enableReserveAsCollateral(weth.address, '75', '80', '105'),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Disable stable borrow rate on the ETH reserve', async () => {
@ -149,20 +149,20 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(stableBorrowRateEnabled).to.be.equal(true);
});
it('Check the onlyLendingPoolManager on disableReserveStableRate', async () => {
it('Check the onlyAaveAdmin on disableReserveStableRate', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).disableReserveStableRate(weth.address),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Check the onlyLendingPoolManager on enableReserveStableRate', async () => {
it('Check the onlyAaveAdmin on enableReserveStableRate', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).enableReserveStableRate(weth.address),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Changes LTV of the reserve', async () => {
@ -172,12 +172,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(ltv.toString()).to.be.bignumber.equal('60', 'Invalid LTV');
});
it('Check the onlyLendingPoolManager on setLtv', async () => {
it('Check the onlyAaveAdmin on setLtv', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).setLtv(weth.address, '75'),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Changes liquidation threshold of the reserve', async () => {
@ -190,12 +190,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
);
});
it('Check the onlyLendingPoolManager on setLiquidationThreshold', async () => {
it('Check the onlyAaveAdmin on setLiquidationThreshold', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).setLiquidationThreshold(weth.address, '80'),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Changes liquidation bonus of the reserve', async () => {
@ -208,28 +208,28 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
);
});
it('Check the onlyLendingPoolManager on setLiquidationBonus', async () => {
it('Check the onlyAaveAdmin on setLiquidationBonus', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).setLiquidationBonus(weth.address, '80'),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Check the onlyLendingPoolManager on setReserveDecimals', async () => {
it('Check the onlyAaveAdmin on setReserveDecimals', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).setReserveDecimals(weth.address, '80'),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Check the onlyLendingPoolManager on setLiquidationBonus', async () => {
it('Check the onlyAaveAdmin on setLiquidationBonus', async () => {
const {configurator, users, weth} = testEnv;
await expect(
configurator.connect(users[2].signer).setLiquidationBonus(weth.address, '80'),
CALLER_NOT_LENDING_POOL_MANAGER
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
CALLER_NOT_AAVE_ADMIN
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Reverts when trying to disable the DAI reserve with liquidity on it', async () => {

View File

@ -14,8 +14,8 @@ makeSuite('LendingPoolAddressesProvider', (testEnv: TestEnv) => {
for (const contractFunction of [
addressesProvider.setLendingPoolImpl,
addressesProvider.setLendingPoolConfiguratorImpl,
addressesProvider.setLendingPoolLiquidationManager,
addressesProvider.setLendingPoolManager,
addressesProvider.setLendingPoolCollateralManager,
addressesProvider.setAaveAdmin,
addressesProvider.setPriceOracle,
addressesProvider.setLendingRateOracle,
]) {

View File

@ -10,9 +10,10 @@ import {
import {MockAToken} from '../types/MockAToken';
import {MockStableDebtToken} from '../types/MockStableDebtToken';
import {MockVariableDebtToken} from '../types/MockVariableDebtToken';
import {ZERO_ADDRESS} from '../helpers/constants';
makeSuite('Upgradeability', (testEnv: TestEnv) => {
const {CALLER_NOT_LENDING_POOL_MANAGER} = ProtocolErrors;
const {CALLER_NOT_AAVE_ADMIN} = ProtocolErrors;
let newATokenAddress: string;
let newStableTokenAddress: string;
let newVariableTokenAddress: string;
@ -24,16 +25,29 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => {
dai.address,
'Aave Interest bearing DAI updated',
'aDAI',
ZERO_ADDRESS,
]);
const stableDebtTokenInstance = await deployContract<MockStableDebtToken>(
eContractid.MockStableDebtToken,
[pool.address, dai.address, 'Aave stable debt bearing DAI updated', 'stableDebtDAI']
[
pool.address,
dai.address,
'Aave stable debt bearing DAI updated',
'stableDebtDAI',
ZERO_ADDRESS,
]
);
const variableDebtTokenInstance = await deployContract<MockVariableDebtToken>(
eContractid.MockVariableDebtToken,
[pool.address, dai.address, 'Aave variable debt bearing DAI updated', 'variableDebtDAI']
[
pool.address,
dai.address,
'Aave variable debt bearing DAI updated',
'variableDebtDAI',
ZERO_ADDRESS,
]
);
newATokenAddress = aTokenInstance.address;
@ -46,7 +60,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => {
await expect(
configurator.connect(users[1].signer).updateAToken(dai.address, newATokenAddress)
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Upgrades the DAI Atoken implementation ', async () => {
@ -68,7 +82,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => {
configurator
.connect(users[1].signer)
.updateStableDebtToken(dai.address, newStableTokenAddress)
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Upgrades the DAI stable debt token implementation ', async () => {
@ -97,7 +111,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => {
configurator
.connect(users[1].signer)
.updateVariableDebtToken(dai.address, newVariableTokenAddress)
).to.be.revertedWith(CALLER_NOT_LENDING_POOL_MANAGER);
).to.be.revertedWith(CALLER_NOT_AAVE_ADMIN);
});
it('Upgrades the DAI variable debt token implementation ', async () => {