Merge branch 'master' into 41-rename-liqudiationmanager

This commit is contained in:
andyk 2020-09-16 15:22:55 +01:00
commit 9594571761
23 changed files with 2531 additions and 8663 deletions

View File

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

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

@ -515,6 +515,11 @@ contract LendingPoolCollateralManager is VersionedInitializable {
address(vars.toReserveAToken), address(vars.toReserveAToken),
vars.amountToReceive 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); vars.toReserveAToken.mint(msg.sender, vars.amountToReceive, toReserve.liquidityIndex);
toReserve.updateInterestRates( toReserve.updateInterestRates(
toAsset, toAsset,

View File

@ -88,6 +88,7 @@ library Errors {
NOT_ENOUGH_LIQUIDITY, NOT_ENOUGH_LIQUIDITY,
NO_ACTIVE_RESERVE, NO_ACTIVE_RESERVE,
HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD, HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD,
INVALID_EQUAL_ASSETS_TO_SWAP INVALID_EQUAL_ASSETS_TO_SWAP,
NO_UNFREEZED_RESERVE
} }
} }

View File

@ -452,10 +452,6 @@ library ValidationLogic {
address fromAsset, address fromAsset,
address toAsset address toAsset
) internal view returns (uint256, string memory) { ) internal view returns (uint256, string memory) {
if (!fromReserve.configuration.getActive() || !toReserve.configuration.getActive()) {
return (uint256(Errors.CollateralManagerErrors.NO_ACTIVE_RESERVE), Errors.NO_ACTIVE_RESERVE);
}
if (fromAsset == toAsset) { if (fromAsset == toAsset) {
return ( return (
uint256(Errors.CollateralManagerErrors.INVALID_EQUAL_ASSETS_TO_SWAP), uint256(Errors.CollateralManagerErrors.INVALID_EQUAL_ASSETS_TO_SWAP),
@ -463,6 +459,17 @@ library ValidationLogic {
); );
} }
(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); return (uint256(Errors.CollateralManagerErrors.NO_ERROR), Errors.NO_ERRORS);
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -82,6 +82,14 @@ interface IAToken is IERC20 {
**/ **/
function scaledBalanceOf(address user) external view returns (uint256); 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. * @dev Used to validate transfers before actually executing them.
* @param user address of the user to check * @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 { import {
iAssetBase,
iAavePoolAssets,
IMarketRates,
iAssetAggregatorBase,
AavePools, AavePools,
eEthereumNetwork,
iAavePoolAssets,
iAssetAggregatorBase,
iAssetBase,
iBasicDistributionParams,
IMarketRates,
iMultiPoolsAssets, iMultiPoolsAssets,
IReserveParams, IReserveParams,
tEthereumAddress, tEthereumAddress,
iBasicDistributionParams,
eEthereumNetwork,
} from './types'; } from './types';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import {getParamPerPool, getParamPerNetwork} from './contracts-helpers'; import {getParamPerNetwork, getParamPerPool} from './contracts-helpers';
export const TEST_SNAPSHOT_ID = '0x1';
export const BUIDLEREVM_CHAINID = 31337;
export const COVERAGE_CHAINID = 1337;
// ---------------- // ----------------
// MATH // MATH

View File

@ -251,49 +251,55 @@ export const deployDefaultReserveInterestRateStrategy = async ([
] ]
); );
export const deployStableDebtToken = async ([name, symbol, underlyingAsset, poolAddress]: [ export const deployStableDebtToken = async ([
string, name,
string, symbol,
tEthereumAddress, underlyingAsset,
tEthereumAddress poolAddress,
]) => { incentivesController,
]: [string, string, tEthereumAddress, tEthereumAddress, tEthereumAddress]) => {
const token = await deployContract<StableDebtToken>(eContractid.StableDebtToken, [ const token = await deployContract<StableDebtToken>(eContractid.StableDebtToken, [
poolAddress, poolAddress,
underlyingAsset, underlyingAsset,
name, name,
symbol, symbol,
incentivesController,
]); ]);
return token; return token;
}; };
export const deployVariableDebtToken = async ([name, symbol, underlyingAsset, poolAddress]: [ export const deployVariableDebtToken = async ([
string, name,
string, symbol,
tEthereumAddress, underlyingAsset,
tEthereumAddress poolAddress,
]) => { incentivesController,
]: [string, string, tEthereumAddress, tEthereumAddress, tEthereumAddress]) => {
const token = await deployContract<VariableDebtToken>(eContractid.VariableDebtToken, [ const token = await deployContract<VariableDebtToken>(eContractid.VariableDebtToken, [
poolAddress, poolAddress,
underlyingAsset, underlyingAsset,
name, name,
symbol, symbol,
incentivesController,
]); ]);
return token; return token;
}; };
export const deployGenericAToken = async ([poolAddress, underlyingAssetAddress, name, symbol]: [ export const deployGenericAToken = async ([
tEthereumAddress, poolAddress,
tEthereumAddress, underlyingAssetAddress,
string, name,
string symbol,
]) => { incentivesController,
]: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress]) => {
const token = await deployContract<AToken>(eContractid.AToken, [ const token = await deployContract<AToken>(eContractid.AToken, [
poolAddress, poolAddress,
underlyingAssetAddress, underlyingAssetAddress,
name, name,
symbol, symbol,
incentivesController,
]); ]);
return token; return token;

View File

@ -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' 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' 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' 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 // require error messages - LendingPool
NOT_ENOUGH_STABLE_BORROW_BALANCE = '21', // 'User does not have any stable rate loan for this reserve' NOT_ENOUGH_STABLE_BORROW_BALANCE = '21', // 'User does not have any stable rate loan for this reserve'

10836
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -175,7 +175,8 @@ const initReserves = async (
lendingPoolAddressesProvider: LendingPoolAddressesProvider, lendingPoolAddressesProvider: LendingPoolAddressesProvider,
lendingPool: LendingPool, lendingPool: LendingPool,
lendingPoolConfigurator: LendingPoolConfigurator, lendingPoolConfigurator: LendingPoolConfigurator,
aavePool: AavePools aavePool: AavePools,
incentivesController: tEthereumAddress
) => { ) => {
if (aavePool !== AavePools.proto && aavePool !== AavePools.secondary) { if (aavePool !== AavePools.proto && aavePool !== AavePools.secondary) {
console.log(`Invalid Aave pool ${aavePool}`); console.log(`Invalid Aave pool ${aavePool}`);
@ -230,6 +231,7 @@ const initReserves = async (
`stableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, `stableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
tokenAddress, tokenAddress,
lendingPool.address, lendingPool.address,
incentivesController,
]); ]);
const variableDebtToken = await deployVariableDebtToken([ const variableDebtToken = await deployVariableDebtToken([
@ -237,6 +239,7 @@ const initReserves = async (
`variableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, `variableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
tokenAddress, tokenAddress,
lendingPool.address, lendingPool.address,
incentivesController,
]); ]);
const aToken = await deployGenericAToken([ const aToken = await deployGenericAToken([
@ -244,6 +247,7 @@ const initReserves = async (
tokenAddress, tokenAddress,
`Aave interest bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, `Aave interest bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
`a${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, `a${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
incentivesController,
]); ]);
if (process.env.POOL === AavePools.secondary) { if (process.env.POOL === AavePools.secondary) {
@ -481,7 +485,8 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
addressesProvider, addressesProvider,
lendingPoolProxy, lendingPoolProxy,
lendingPoolConfiguratorProxy, lendingPoolConfiguratorProxy,
AavePools.proto AavePools.proto,
ZERO_ADDRESS
); );
await enableReservesToBorrow( await enableReservesToBorrow(
reservesParams, reservesParams,

View File

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

View File

@ -13,12 +13,63 @@ const {expect} = require('chai');
makeSuite('LendingPool SwapDeposit function', (testEnv: TestEnv) => { makeSuite('LendingPool SwapDeposit function', (testEnv: TestEnv) => {
let _mockSwapAdapter = {} as MockSwapAdapter; 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 () => { before(async () => {
_mockSwapAdapter = await getMockSwapAdapter(); _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 () => { it('Deposits WETH into the reserve', async () => {
const {pool, weth, users} = testEnv; const {pool, weth, users} = testEnv;
const amountToDeposit = ethers.utils.parseEther('1'); const amountToDeposit = ethers.utils.parseEther('1');
@ -32,6 +83,7 @@ makeSuite('LendingPool SwapDeposit function', (testEnv: TestEnv) => {
.deposit(weth.address, amountToDeposit, await signer.getAddress(), '0'); .deposit(weth.address, amountToDeposit, await signer.getAddress(), '0');
} }
}); });
it('User tries to swap more then he can, revert expected', async () => { it('User tries to swap more then he can, revert expected', async () => {
const {pool, weth, dai} = testEnv; const {pool, weth, dai} = testEnv;
await expect( await expect(
@ -45,19 +97,6 @@ makeSuite('LendingPool SwapDeposit function', (testEnv: TestEnv) => {
).to.be.revertedWith('55'); ).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 () => { it('User tries to swap more then available on the reserve', async () => {
const {pool, weth, dai, users, aEth, deployer} = testEnv; const {pool, weth, dai, users, aEth, deployer} = testEnv;
@ -134,6 +173,9 @@ makeSuite('LendingPool SwapDeposit function', (testEnv: TestEnv) => {
reserveBalanceDAIBefore.add(amountToReturn).toString(), reserveBalanceDAIBefore.add(amountToReturn).toString(),
'was received incorrect amount if reserve funds' '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 () => { 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 () => { 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(); const userAddress = await pool.signer.getAddress();
// add more liquidity to allow user 0 to swap everything he has // 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' '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

@ -10,6 +10,7 @@ import {
import {MockAToken} from '../types/MockAToken'; import {MockAToken} from '../types/MockAToken';
import {MockStableDebtToken} from '../types/MockStableDebtToken'; import {MockStableDebtToken} from '../types/MockStableDebtToken';
import {MockVariableDebtToken} from '../types/MockVariableDebtToken'; import {MockVariableDebtToken} from '../types/MockVariableDebtToken';
import {ZERO_ADDRESS} from '../helpers/constants';
makeSuite('Upgradeability', (testEnv: TestEnv) => { makeSuite('Upgradeability', (testEnv: TestEnv) => {
const {CALLER_NOT_AAVE_ADMIN} = ProtocolErrors; const {CALLER_NOT_AAVE_ADMIN} = ProtocolErrors;
@ -24,16 +25,29 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => {
dai.address, dai.address,
'Aave Interest bearing DAI updated', 'Aave Interest bearing DAI updated',
'aDAI', 'aDAI',
ZERO_ADDRESS,
]); ]);
const stableDebtTokenInstance = await deployContract<MockStableDebtToken>( const stableDebtTokenInstance = await deployContract<MockStableDebtToken>(
eContractid.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>( const variableDebtTokenInstance = await deployContract<MockVariableDebtToken>(
eContractid.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; newATokenAddress = aTokenInstance.address;