mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Merge branch 'master' into feat/data-helpers
This commit is contained in:
commit
898d72dfb3
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -9,7 +9,10 @@ build/
|
|||
.idea
|
||||
types
|
||||
|
||||
deployed-contracts.json
|
||||
|
||||
coverage
|
||||
.coverage_artifacts
|
||||
.coverage_cache
|
||||
.coverage_contracts
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ usePlugin('@nomiclabs/buidler-etherscan');
|
|||
usePlugin('buidler-gas-reporter');
|
||||
|
||||
const SKIP_LOAD = process.env.SKIP_LOAD === 'true';
|
||||
const DEFAULT_BLOCK_GAS_LIMIT = 10000000;
|
||||
const DEFAULT_BLOCK_GAS_LIMIT = 12000000;
|
||||
const DEFAULT_GAS_PRICE = 10;
|
||||
const HARDFORK = 'istanbul';
|
||||
const INFURA_KEY = process.env.INFURA_KEY || '';
|
||||
|
|
|
@ -20,7 +20,7 @@ contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesP
|
|||
/**
|
||||
* @dev returns if an addressesProvider is registered or not
|
||||
* @param provider the addresses provider
|
||||
* @return true if the addressesProvider is registered, false otherwise
|
||||
* @return The id of the addresses provider or 0 if the addresses provider not registered
|
||||
**/
|
||||
function isAddressesProviderRegistered(address provider)
|
||||
external
|
||||
|
@ -33,7 +33,7 @@ contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesP
|
|||
|
||||
/**
|
||||
* @dev returns the list of active addressesProviders
|
||||
* @return the list of addressesProviders
|
||||
* @return the list of addressesProviders, potentially containing address(0) elements
|
||||
**/
|
||||
function getAddressesProvidersList() external override view returns (address[] memory) {
|
||||
address[] memory addressesProvidersList = _addressesProvidersList;
|
||||
|
@ -91,7 +91,7 @@ contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesP
|
|||
|
||||
/**
|
||||
* @dev Returns the id on an `addressesProvider` or address(0) if not registered
|
||||
* @return The id or address(0)
|
||||
* @return The id or 0 if the addresses provider is not registered
|
||||
*/
|
||||
function getAddressesProviderIdByAddress(address addressesProvider)
|
||||
external
|
||||
|
|
122
contracts/deployments/ATokensAndRatesHelper.sol
Normal file
122
contracts/deployments/ATokensAndRatesHelper.sol
Normal file
|
@ -0,0 +1,122 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {LendingPool} from '../lendingpool/LendingPool.sol';
|
||||
import {LendingPoolAddressesProvider} from '../configuration/LendingPoolAddressesProvider.sol';
|
||||
import {LendingPoolConfigurator} from '../lendingpool/LendingPoolConfigurator.sol';
|
||||
import {AToken} from '../tokenization/AToken.sol';
|
||||
import {
|
||||
DefaultReserveInterestRateStrategy
|
||||
} from '../lendingpool/DefaultReserveInterestRateStrategy.sol';
|
||||
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
|
||||
import {StringLib} from '../libraries/helpers/StringLib.sol';
|
||||
|
||||
contract ATokensAndRatesHelper is Ownable {
|
||||
address payable private pool;
|
||||
address private addressesProvider;
|
||||
address private poolConfigurator;
|
||||
event deployedContracts(address aToken, address strategy);
|
||||
|
||||
constructor(
|
||||
address payable _pool,
|
||||
address _addressesProvider,
|
||||
address _poolConfigurator
|
||||
) public {
|
||||
pool = _pool;
|
||||
addressesProvider = _addressesProvider;
|
||||
poolConfigurator = _poolConfigurator;
|
||||
}
|
||||
|
||||
function initDeployment(
|
||||
address[] calldata tokens,
|
||||
string[] calldata symbols,
|
||||
uint256[5][] calldata rates,
|
||||
address incentivesController
|
||||
) external onlyOwner {
|
||||
require(tokens.length == symbols.length, 't Arrays not same length');
|
||||
require(rates.length == symbols.length, 'r Arrays not same length');
|
||||
|
||||
for (uint256 i = 0; i < tokens.length; i++) {
|
||||
emit deployedContracts(
|
||||
address(
|
||||
new AToken(
|
||||
LendingPool(pool),
|
||||
tokens[i],
|
||||
address(0),
|
||||
StringLib.concat('Aave interest bearing ', symbols[i]),
|
||||
StringLib.concat('a', symbols[i]),
|
||||
incentivesController
|
||||
)
|
||||
),
|
||||
address(
|
||||
new DefaultReserveInterestRateStrategy(
|
||||
LendingPoolAddressesProvider(addressesProvider),
|
||||
rates[i][0],
|
||||
rates[i][1],
|
||||
rates[i][2],
|
||||
rates[i][3],
|
||||
rates[i][4]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function initReserve(
|
||||
address[] calldata stables,
|
||||
address[] calldata variables,
|
||||
address[] calldata aTokens,
|
||||
address[] calldata strategies,
|
||||
uint8[] calldata reserveDecimals
|
||||
) external onlyOwner {
|
||||
require(variables.length == stables.length);
|
||||
require(aTokens.length == stables.length);
|
||||
require(strategies.length == stables.length);
|
||||
require(reserveDecimals.length == stables.length);
|
||||
|
||||
for (uint256 i = 0; i < stables.length; i++) {
|
||||
LendingPoolConfigurator(poolConfigurator).initReserve(
|
||||
aTokens[i],
|
||||
stables[i],
|
||||
variables[i],
|
||||
reserveDecimals[i],
|
||||
strategies[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function enableReservesAsCollateral(
|
||||
address[] calldata tokens,
|
||||
uint256[] calldata baseLTVs,
|
||||
uint256[] calldata liquidationThresholds,
|
||||
uint256[] calldata liquidationBonuses
|
||||
) external onlyOwner {
|
||||
require(baseLTVs.length == tokens.length);
|
||||
require(liquidationThresholds.length == tokens.length);
|
||||
require(liquidationBonuses.length == tokens.length);
|
||||
|
||||
for (uint256 i = 0; i < tokens.length; i++) {
|
||||
LendingPoolConfigurator(poolConfigurator).enableReserveAsCollateral(
|
||||
tokens[i],
|
||||
baseLTVs[i],
|
||||
liquidationThresholds[i],
|
||||
liquidationBonuses[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function enableBorrowingOnReserves(address[] calldata tokens, bool[] calldata stableBorrows)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
require(stableBorrows.length == tokens.length);
|
||||
|
||||
for (uint256 i = 0; i < tokens.length; i++) {
|
||||
LendingPoolConfigurator(poolConfigurator).enableBorrowingOnReserve(
|
||||
tokens[i],
|
||||
stableBorrows[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
70
contracts/deployments/StableAndVariableTokensHelper.sol
Normal file
70
contracts/deployments/StableAndVariableTokensHelper.sol
Normal file
|
@ -0,0 +1,70 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {StableDebtToken} from '../tokenization/StableDebtToken.sol';
|
||||
import {VariableDebtToken} from '../tokenization/VariableDebtToken.sol';
|
||||
import {LendingRateOracle} from '../mocks/oracle/LendingRateOracle.sol';
|
||||
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
|
||||
import {StringLib} from '../libraries/helpers/StringLib.sol';
|
||||
|
||||
contract StableAndVariableTokensHelper is Ownable {
|
||||
address payable private pool;
|
||||
address private addressesProvider;
|
||||
event deployedContracts(address stableToken, address variableToken);
|
||||
|
||||
constructor(address payable _pool, address _addressesProvider) public {
|
||||
pool = _pool;
|
||||
addressesProvider = _addressesProvider;
|
||||
}
|
||||
|
||||
function initDeployment(
|
||||
address[] calldata tokens,
|
||||
string[] calldata symbols,
|
||||
address incentivesController
|
||||
) external onlyOwner {
|
||||
require(tokens.length == symbols.length, 'Arrays not same length');
|
||||
require(pool != address(0), 'Pool can not be zero address');
|
||||
for (uint256 i = 0; i < tokens.length; i++) {
|
||||
emit deployedContracts(
|
||||
address(
|
||||
new StableDebtToken(
|
||||
pool,
|
||||
tokens[i],
|
||||
StringLib.concat('Aave stable debt bearing ', symbols[i]),
|
||||
StringLib.concat('stableDebt', symbols[i]),
|
||||
incentivesController
|
||||
)
|
||||
),
|
||||
address(
|
||||
new VariableDebtToken(
|
||||
pool,
|
||||
tokens[i],
|
||||
StringLib.concat('Aave variable debt bearing ', symbols[i]),
|
||||
StringLib.concat('variableDebt', symbols[i]),
|
||||
incentivesController
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function setOracleBorrowRates(
|
||||
address[] calldata assets,
|
||||
uint256[] calldata rates,
|
||||
address oracle
|
||||
) external onlyOwner {
|
||||
require(assets.length == rates.length, 'Arrays not same length');
|
||||
|
||||
for (uint256 i = 0; i < assets.length; i++) {
|
||||
// LendingRateOracle owner must be this contract
|
||||
LendingRateOracle(oracle).setMarketBorrowRate(assets[i], rates[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function setOracleOwnership(address oracle, address admin) external onlyOwner {
|
||||
require(admin != address(0), 'owner can not be zero');
|
||||
require(LendingRateOracle(oracle).owner() == address(this), 'helper is not owner');
|
||||
LendingRateOracle(oracle).transferOwnership(admin);
|
||||
}
|
||||
}
|
|
@ -99,6 +99,8 @@ interface ILendingPool {
|
|||
/**
|
||||
* @dev emitted when a flashloan is executed
|
||||
* @param target the address of the flashLoanReceiver
|
||||
* @param mode Type of the debt to open if the flash loan is not returned. 0 -> Don't open any debt, just revert, 1 -> stable, 2 -> variable
|
||||
* @param onBehalfOf the address incurring the debt, if borrow mode is not 0
|
||||
* @param assets the address of the assets being flashborrowed
|
||||
* @param amounts the amount requested
|
||||
* @param premiums the total fee on the amount
|
||||
|
@ -107,6 +109,7 @@ interface ILendingPool {
|
|||
event FlashLoan(
|
||||
address indexed target,
|
||||
uint256 mode,
|
||||
address indexed onBehalfOf,
|
||||
address[] assets,
|
||||
uint256[] amounts,
|
||||
uint256[] premiums,
|
||||
|
@ -162,7 +165,6 @@ interface ILendingPool {
|
|||
address indexed reserve,
|
||||
uint256 liquidityRate,
|
||||
uint256 stableBorrowRate,
|
||||
uint256 averageStableBorrowRate,
|
||||
uint256 variableBorrowRate,
|
||||
uint256 liquidityIndex,
|
||||
uint256 variableBorrowIndex
|
||||
|
@ -296,6 +298,7 @@ interface ILendingPool {
|
|||
address[] calldata assets,
|
||||
uint256[] calldata amounts,
|
||||
uint256 mode,
|
||||
address onBehalfOf,
|
||||
bytes calldata params,
|
||||
uint16 referralCode
|
||||
) external;
|
||||
|
@ -350,11 +353,14 @@ interface ILendingPool {
|
|||
|
||||
function getReserveData(address asset) external view returns (ReserveLogic.ReserveData memory);
|
||||
|
||||
function balanceDecreaseAllowed(
|
||||
address reserve,
|
||||
address user,
|
||||
uint256 amount
|
||||
) external view returns (bool);
|
||||
function finalizeTransfer(
|
||||
address asset,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
uint256 balanceFromAfter,
|
||||
uint256 balanceToBefore
|
||||
) external;
|
||||
|
||||
function getReservesList() external view returns (address[] memory);
|
||||
|
||||
|
|
|
@ -503,6 +503,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
* @param assets The addresss of the assets being flashborrowed
|
||||
* @param amounts The amounts requested for this flashloan for each asset
|
||||
* @param mode Type of the debt to open if the flash loan is not returned. 0 -> Don't open any debt, just revert, 1 -> stable, 2 -> variable
|
||||
* @param onBehalfOf If mode is not 0, then the address to take the debt onBehalfOf. The onBehalfOf address must already have approved `msg.sender` to incur the debt on their behalf.
|
||||
* @param params Variadic packed params to pass to the receiver as extra information
|
||||
* @param referralCode Referral code of the flash loan
|
||||
**/
|
||||
|
@ -511,6 +512,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
address[] calldata assets,
|
||||
uint256[] calldata amounts,
|
||||
uint256 mode,
|
||||
address onBehalfOf,
|
||||
bytes calldata params,
|
||||
uint16 referralCode
|
||||
) external override {
|
||||
|
@ -568,13 +570,23 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
vars.currentAmountPlusPremium
|
||||
);
|
||||
} else {
|
||||
if (msg.sender != onBehalfOf) {
|
||||
address debtToken = _reserves[vars.currentAsset].getDebtTokenAddress(mode);
|
||||
|
||||
_borrowAllowance[debtToken][onBehalfOf][msg
|
||||
.sender] = _borrowAllowance[debtToken][onBehalfOf][msg.sender].sub(
|
||||
vars.currentAmount,
|
||||
Errors.BORROW_ALLOWANCE_ARE_NOT_ENOUGH
|
||||
);
|
||||
}
|
||||
|
||||
//if the user didn't choose to return the funds, the system checks if there
|
||||
//is enough collateral and eventually open a position
|
||||
_executeBorrow(
|
||||
ExecuteBorrowParams(
|
||||
vars.currentAsset,
|
||||
msg.sender,
|
||||
msg.sender,
|
||||
onBehalfOf,
|
||||
vars.currentAmount,
|
||||
mode,
|
||||
vars.currentATokenAddress,
|
||||
|
@ -583,7 +595,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
)
|
||||
);
|
||||
}
|
||||
emit FlashLoan(receiverAddress, mode, assets, amounts, premiums, referralCode);
|
||||
emit FlashLoan(receiverAddress, mode, onBehalfOf, assets, amounts, premiums, referralCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -724,29 +736,48 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
}
|
||||
|
||||
/**
|
||||
* @dev validate if a balance decrease for an asset is allowed
|
||||
* @dev validates and finalizes an aToken transfer
|
||||
* @param asset the address of the reserve
|
||||
* @param user the user related to the balance decrease
|
||||
* @param from the user from which the aTokens are transferred
|
||||
* @param to the user receiving the aTokens
|
||||
* @param amount the amount being transferred/redeemed
|
||||
* @return true if the balance decrease can be allowed, false otherwise
|
||||
* @param balanceFromBefore the balance of the from user before the transfer
|
||||
* @param balanceToBefore the balance of the to user before the transfer
|
||||
*/
|
||||
function balanceDecreaseAllowed(
|
||||
function finalizeTransfer(
|
||||
address asset,
|
||||
address user,
|
||||
uint256 amount
|
||||
) external override view returns (bool) {
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount,
|
||||
uint256 balanceFromBefore,
|
||||
uint256 balanceToBefore
|
||||
) external override {
|
||||
_whenNotPaused();
|
||||
return
|
||||
GenericLogic.balanceDecreaseAllowed(
|
||||
asset,
|
||||
user,
|
||||
amount,
|
||||
_reserves,
|
||||
_usersConfig[user],
|
||||
_reservesList,
|
||||
_reservesCount,
|
||||
_addressesProvider.getPriceOracle()
|
||||
);
|
||||
|
||||
require(msg.sender == _reserves[asset].aTokenAddress, Errors.CALLER_MUST_BE_AN_ATOKEN);
|
||||
|
||||
ValidationLogic.validateTransfer(
|
||||
from,
|
||||
_reserves,
|
||||
_usersConfig[from],
|
||||
_reservesList,
|
||||
_reservesCount,
|
||||
_addressesProvider.getPriceOracle()
|
||||
);
|
||||
|
||||
uint256 reserveId = _reserves[asset].id;
|
||||
|
||||
if (from != to) {
|
||||
if (balanceFromBefore.sub(amount) == 0) {
|
||||
UserConfiguration.Map storage fromConfig = _usersConfig[from];
|
||||
fromConfig.setUsingAsCollateral(reserveId, false);
|
||||
}
|
||||
|
||||
if (balanceToBefore == 0 && amount != 0) {
|
||||
UserConfiguration.Map storage toConfig = _usersConfig[to];
|
||||
toConfig.setUsingAsCollateral(reserveId, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -913,13 +944,15 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
* @dev adds a reserve to the array of the _reserves address
|
||||
**/
|
||||
function _addReserveToList(address asset) internal {
|
||||
require(_reservesCount < MAX_NUMBER_RESERVES, Errors.NO_MORE_RESERVES_ALLOWED);
|
||||
uint256 reservesCount = _reservesCount;
|
||||
|
||||
require(reservesCount < MAX_NUMBER_RESERVES, Errors.NO_MORE_RESERVES_ALLOWED);
|
||||
|
||||
bool reserveAlreadyAdded = _reserves[asset].id != 0 || _reservesList[0] == asset;
|
||||
|
||||
if (!reserveAlreadyAdded) {
|
||||
_reserves[asset].id = uint8(_reservesCount);
|
||||
_reservesList[_reservesCount] = asset;
|
||||
_reserves[asset].id = uint8(reservesCount);
|
||||
_reservesList[reservesCount] = asset;
|
||||
|
||||
_reservesCount++;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
|
||||
import {Errors} from '../helpers/Errors.sol';
|
||||
|
||||
/**
|
||||
* @title ReserveConfiguration library
|
||||
* @author Aave
|
||||
* @notice Implements the bitmap logic to handle the reserve configuration
|
||||
*/
|
||||
library ReserveConfiguration {
|
||||
uint256 constant LTV_MASK = 0xFFFFFFFFFFFFFFFF0000;
|
||||
uint256 constant LIQUIDATION_THRESHOLD_MASK = 0xFFFFFFFFFFFF0000FFFF;
|
||||
uint256 constant LIQUIDATION_BONUS_MASK = 0xFFFFFFFF0000FFFFFFFF;
|
||||
uint256 constant DECIMALS_MASK = 0xFFFFFF00FFFFFFFFFFFF;
|
||||
uint256 constant ACTIVE_MASK = 0xFFFFFEFFFFFFFFFFFFFF;
|
||||
uint256 constant FROZEN_MASK = 0xFFFFFDFFFFFFFFFFFFFF;
|
||||
uint256 constant BORROWING_MASK = 0xFFFFFBFFFFFFFFFFFFFF;
|
||||
uint256 constant STABLE_BORROWING_MASK = 0xFFFFF7FFFFFFFFFFFFFF;
|
||||
uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFF;
|
||||
uint256 constant LTV_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000; // prettier-ignore
|
||||
uint256 constant LIQUIDATION_THRESHOLD_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF; // prettier-ignore
|
||||
uint256 constant LIQUIDATION_BONUS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF; // prettier-ignore
|
||||
uint256 constant DECIMALS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF; // prettier-ignore
|
||||
uint256 constant ACTIVE_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFF; // prettier-ignore
|
||||
uint256 constant FROZEN_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFF; // prettier-ignore
|
||||
uint256 constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore
|
||||
uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore
|
||||
uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore
|
||||
|
||||
/// @dev For the LTV, the start bit is 0 (up to 15), but we don't declare it as for 0 no bit movement is needed
|
||||
uint256 constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16;
|
||||
|
@ -27,6 +29,12 @@ library ReserveConfiguration {
|
|||
uint256 constant STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59;
|
||||
uint256 constant RESERVE_FACTOR_START_BIT_POSITION = 64;
|
||||
|
||||
uint256 constant MAX_VALID_LTV = 65535;
|
||||
uint256 constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535;
|
||||
uint256 constant MAX_VALID_LIQUIDATION_BONUS = 65535;
|
||||
uint256 constant MAX_VALID_DECIMALS = 255;
|
||||
uint256 constant MAX_VALID_RESERVE_FACTOR = 65535;
|
||||
|
||||
struct Map {
|
||||
//bit 0-15: LTV
|
||||
//bit 16-31: Liq. threshold
|
||||
|
@ -47,6 +55,8 @@ library ReserveConfiguration {
|
|||
* @param ltv the new ltv
|
||||
**/
|
||||
function setLtv(ReserveConfiguration.Map memory self, uint256 ltv) internal pure {
|
||||
require(ltv <= MAX_VALID_LTV, Errors.INVALID_LTV);
|
||||
|
||||
self.data = (self.data & LTV_MASK) | ltv;
|
||||
}
|
||||
|
||||
|
@ -68,6 +78,8 @@ library ReserveConfiguration {
|
|||
internal
|
||||
pure
|
||||
{
|
||||
require(threshold <= MAX_VALID_LIQUIDATION_THRESHOLD, Errors.INVALID_LIQ_THRESHOLD);
|
||||
|
||||
self.data =
|
||||
(self.data & LIQUIDATION_THRESHOLD_MASK) |
|
||||
(threshold << LIQUIDATION_THRESHOLD_START_BIT_POSITION);
|
||||
|
@ -92,6 +104,8 @@ library ReserveConfiguration {
|
|||
* @param bonus the new liquidation bonus
|
||||
**/
|
||||
function setLiquidationBonus(ReserveConfiguration.Map memory self, uint256 bonus) internal pure {
|
||||
require(bonus <= MAX_VALID_LIQUIDATION_BONUS, Errors.INVALID_LIQ_BONUS);
|
||||
|
||||
self.data =
|
||||
(self.data & LIQUIDATION_BONUS_MASK) |
|
||||
(bonus << LIQUIDATION_BONUS_START_BIT_POSITION);
|
||||
|
@ -116,6 +130,8 @@ library ReserveConfiguration {
|
|||
* @param decimals the decimals
|
||||
**/
|
||||
function setDecimals(ReserveConfiguration.Map memory self, uint256 decimals) internal pure {
|
||||
require(decimals <= MAX_VALID_DECIMALS, Errors.INVALID_DECIMALS);
|
||||
|
||||
self.data = (self.data & DECIMALS_MASK) | (decimals << RESERVE_DECIMALS_START_BIT_POSITION);
|
||||
}
|
||||
|
||||
|
@ -145,7 +161,7 @@ library ReserveConfiguration {
|
|||
* @return the active state
|
||||
**/
|
||||
function getActive(ReserveConfiguration.Map storage self) internal view returns (bool) {
|
||||
return ((self.data & ~ACTIVE_MASK) >> IS_ACTIVE_START_BIT_POSITION) != 0;
|
||||
return (self.data & ~ACTIVE_MASK) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -165,7 +181,7 @@ library ReserveConfiguration {
|
|||
* @return the frozen state
|
||||
**/
|
||||
function getFrozen(ReserveConfiguration.Map storage self) internal view returns (bool) {
|
||||
return ((self.data & ~FROZEN_MASK) >> IS_FROZEN_START_BIT_POSITION) != 0;
|
||||
return (self.data & ~FROZEN_MASK) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,7 +201,7 @@ library ReserveConfiguration {
|
|||
* @return the borrowing state
|
||||
**/
|
||||
function getBorrowingEnabled(ReserveConfiguration.Map storage self) internal view returns (bool) {
|
||||
return ((self.data & ~BORROWING_MASK) >> BORROWING_ENABLED_START_BIT_POSITION) != 0;
|
||||
return (self.data & ~BORROWING_MASK) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -212,8 +228,7 @@ library ReserveConfiguration {
|
|||
view
|
||||
returns (bool)
|
||||
{
|
||||
return
|
||||
((self.data & ~STABLE_BORROWING_MASK) >> STABLE_BORROWING_ENABLED_START_BIT_POSITION) != 0;
|
||||
return (self.data & ~STABLE_BORROWING_MASK) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,6 +240,8 @@ library ReserveConfiguration {
|
|||
internal
|
||||
pure
|
||||
{
|
||||
require(reserveFactor <= MAX_VALID_RESERVE_FACTOR, Errors.INVALID_RESERVE_FACTOR);
|
||||
|
||||
self.data =
|
||||
(self.data & RESERVE_FACTOR_MASK) |
|
||||
(reserveFactor << RESERVE_FACTOR_START_BIT_POSITION);
|
||||
|
@ -257,10 +274,10 @@ library ReserveConfiguration {
|
|||
uint256 dataLocal = self.data;
|
||||
|
||||
return (
|
||||
(dataLocal & ~ACTIVE_MASK) >> IS_ACTIVE_START_BIT_POSITION != 0,
|
||||
(dataLocal & ~FROZEN_MASK) >> IS_FROZEN_START_BIT_POSITION != 0,
|
||||
(dataLocal & ~BORROWING_MASK) >> BORROWING_ENABLED_START_BIT_POSITION != 0,
|
||||
(dataLocal & ~STABLE_BORROWING_MASK) >> STABLE_BORROWING_ENABLED_START_BIT_POSITION != 0
|
||||
(dataLocal & ~ACTIVE_MASK) != 0,
|
||||
(dataLocal & ~FROZEN_MASK) != 0,
|
||||
(dataLocal & ~BORROWING_MASK) != 0,
|
||||
(dataLocal & ~STABLE_BORROWING_MASK) != 0
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -316,8 +333,7 @@ library ReserveConfiguration {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* @dev gets the configuration flags of the reserve from a memory object
|
||||
* @param self the reserve configuration
|
||||
* @return the state flags representing active, freezed, borrowing enabled, stableRateBorrowing enabled
|
||||
|
@ -333,10 +349,10 @@ library ReserveConfiguration {
|
|||
)
|
||||
{
|
||||
return (
|
||||
(self.data & ~ACTIVE_MASK) >> IS_ACTIVE_START_BIT_POSITION != 0,
|
||||
(self.data & ~FROZEN_MASK) >> IS_FROZEN_START_BIT_POSITION != 0,
|
||||
(self.data & ~BORROWING_MASK) >> BORROWING_ENABLED_START_BIT_POSITION != 0,
|
||||
(self.data & ~STABLE_BORROWING_MASK) >> STABLE_BORROWING_ENABLED_START_BIT_POSITION != 0
|
||||
(self.data & ~ACTIVE_MASK) != 0,
|
||||
(self.data & ~FROZEN_MASK) != 0,
|
||||
(self.data & ~BORROWING_MASK) != 0,
|
||||
(self.data & ~STABLE_BORROWING_MASK) != 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ library Errors {
|
|||
string public constant NO_MORE_RESERVES_ALLOWED = '59';
|
||||
string public constant INVALID_FLASH_LOAN_EXECUTOR_RETURN = '60';
|
||||
string public constant INCONSISTENT_FLASHLOAN_PARAMS = '69';
|
||||
string public constant CALLER_MUST_BE_AN_ATOKEN = '76';
|
||||
|
||||
// require error messages - aToken - DebtTokens
|
||||
string public constant CALLER_MUST_BE_LENDING_POOL = '28'; // 'The caller of this function must be a lending pool'
|
||||
|
@ -89,6 +90,14 @@ library Errors {
|
|||
|
||||
// pausable error message
|
||||
string public constant IS_PAUSED = '58'; // 'Pool is paused'
|
||||
|
||||
// Reserve configuration
|
||||
string public constant INVALID_LTV = '70';
|
||||
string public constant INVALID_LIQ_THRESHOLD = '71';
|
||||
string public constant INVALID_LIQ_BONUS = '72';
|
||||
string public constant INVALID_DECIMALS = '73';
|
||||
string public constant INVALID_RESERVE_FACTOR = '74';
|
||||
|
||||
enum CollateralManagerErrors {
|
||||
NO_ERROR,
|
||||
NO_COLLATERAL_AVAILABLE,
|
||||
|
|
8
contracts/libraries/helpers/StringLib.sol
Normal file
8
contracts/libraries/helpers/StringLib.sol
Normal file
|
@ -0,0 +1,8 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
|
||||
library StringLib {
|
||||
function concat(string memory a, string memory b) internal pure returns (string memory) {
|
||||
return string(abi.encodePacked(a, b));
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ library GenericLogic {
|
|||
uint256 borrowBalanceETH;
|
||||
uint256 avgLiquidationThreshold;
|
||||
uint256 amountToDecreaseETH;
|
||||
uint256 collateralBalancefterDecrease;
|
||||
uint256 collateralBalanceAfterDecrease;
|
||||
uint256 liquidationThresholdAfterDecrease;
|
||||
uint256 healthFactorAfterDecrease;
|
||||
bool reserveUsageAsCollateralEnabled;
|
||||
|
@ -91,10 +91,10 @@ library GenericLogic {
|
|||
10**vars.decimals
|
||||
);
|
||||
|
||||
vars.collateralBalancefterDecrease = vars.collateralBalanceETH.sub(vars.amountToDecreaseETH);
|
||||
vars.collateralBalanceAfterDecrease = vars.collateralBalanceETH.sub(vars.amountToDecreaseETH);
|
||||
|
||||
//if there is a borrow, there can't be 0 collateral
|
||||
if (vars.collateralBalancefterDecrease == 0) {
|
||||
if (vars.collateralBalanceAfterDecrease == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -102,15 +102,15 @@ library GenericLogic {
|
|||
.collateralBalanceETH
|
||||
.mul(vars.avgLiquidationThreshold)
|
||||
.sub(vars.amountToDecreaseETH.mul(vars.liquidationThreshold))
|
||||
.div(vars.collateralBalancefterDecrease);
|
||||
.div(vars.collateralBalanceAfterDecrease);
|
||||
|
||||
uint256 healthFactorAfterDecrease = calculateHealthFactorFromBalances(
|
||||
vars.collateralBalancefterDecrease,
|
||||
vars.collateralBalanceAfterDecrease,
|
||||
vars.borrowBalanceETH,
|
||||
vars.liquidationThresholdAfterDecrease
|
||||
);
|
||||
|
||||
return healthFactorAfterDecrease > GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD;
|
||||
return healthFactorAfterDecrease >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD;
|
||||
}
|
||||
|
||||
struct CalculateUserAccountDataVars {
|
||||
|
|
|
@ -151,12 +151,14 @@ library ReserveLogic {
|
|||
.scaledTotalSupply();
|
||||
uint256 previousVariableBorrowIndex = reserve.variableBorrowIndex;
|
||||
uint256 previousLiquidityIndex = reserve.liquidityIndex;
|
||||
uint40 lastUpdatedTimestamp = reserve.lastUpdateTimestamp;
|
||||
|
||||
(uint256 newLiquidityIndex, uint256 newVariableBorrowIndex) = _updateIndexes(
|
||||
reserve,
|
||||
scaledVariableDebt,
|
||||
previousLiquidityIndex,
|
||||
previousVariableBorrowIndex
|
||||
previousVariableBorrowIndex,
|
||||
lastUpdatedTimestamp
|
||||
);
|
||||
|
||||
_mintToTreasury(
|
||||
|
@ -164,7 +166,8 @@ library ReserveLogic {
|
|||
scaledVariableDebt,
|
||||
previousVariableBorrowIndex,
|
||||
newLiquidityIndex,
|
||||
newVariableBorrowIndex
|
||||
newVariableBorrowIndex,
|
||||
lastUpdatedTimestamp
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -318,7 +321,8 @@ library ReserveLogic {
|
|||
uint256 scaledVariableDebt,
|
||||
uint256 previousVariableBorrowIndex,
|
||||
uint256 newLiquidityIndex,
|
||||
uint256 newVariableBorrowIndex
|
||||
uint256 newVariableBorrowIndex,
|
||||
uint40 timestamp
|
||||
) internal {
|
||||
MintToTreasuryLocalVars memory vars;
|
||||
|
||||
|
@ -345,7 +349,8 @@ library ReserveLogic {
|
|||
//calculate the stable debt until the last timestamp update
|
||||
vars.cumulatedStableInterest = MathUtils.calculateCompoundedInterest(
|
||||
vars.avgStableRate,
|
||||
vars.stableSupplyUpdatedTimestamp
|
||||
vars.stableSupplyUpdatedTimestamp,
|
||||
timestamp
|
||||
);
|
||||
|
||||
vars.previousStableDebt = vars.principalStableDebt.rayMul(vars.cumulatedStableInterest);
|
||||
|
@ -375,10 +380,9 @@ library ReserveLogic {
|
|||
ReserveData storage reserve,
|
||||
uint256 scaledVariableDebt,
|
||||
uint256 liquidityIndex,
|
||||
uint256 variableBorrowIndex
|
||||
uint256 variableBorrowIndex,
|
||||
uint40 timestamp
|
||||
) internal returns (uint256, uint256) {
|
||||
uint40 timestamp = reserve.lastUpdateTimestamp;
|
||||
|
||||
uint256 currentLiquidityRate = reserve.currentLiquidityRate;
|
||||
|
||||
uint256 newLiquidityIndex = liquidityIndex;
|
||||
|
|
|
@ -46,6 +46,11 @@ library ValidationLogic {
|
|||
* @param reserveAddress the address of the reserve
|
||||
* @param amount the amount to be withdrawn
|
||||
* @param userBalance the balance of the user
|
||||
* @param reservesData the reserves state
|
||||
* @param userConfig the user configuration
|
||||
* @param reserves the addresses of the reserves
|
||||
* @param reservesCount the number of reserves
|
||||
* @param oracle the price oracle
|
||||
*/
|
||||
function validateWithdraw(
|
||||
address reserveAddress,
|
||||
|
@ -389,4 +394,35 @@ library ValidationLogic {
|
|||
|
||||
return (uint256(Errors.CollateralManagerErrors.NO_ERROR), Errors.NO_ERRORS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev validates an aToken transfer.
|
||||
* @param from the user from which the aTokens are being transferred
|
||||
* @param reservesData the state of all the reserves
|
||||
* @param userConfig the state of the user for the specific reserve
|
||||
* @param reserves the addresses of all the active reserves
|
||||
* @param oracle the price oracle
|
||||
*/
|
||||
function validateTransfer(
|
||||
address from,
|
||||
mapping(address => ReserveLogic.ReserveData) storage reservesData,
|
||||
UserConfiguration.Map storage userConfig,
|
||||
mapping(uint256 => address) storage reserves,
|
||||
uint256 reservesCount,
|
||||
address oracle
|
||||
) internal view {
|
||||
(, , , , uint256 healthFactor) = GenericLogic.calculateUserAccountData(
|
||||
from,
|
||||
reservesData,
|
||||
userConfig,
|
||||
reserves,
|
||||
reservesCount,
|
||||
oracle
|
||||
);
|
||||
|
||||
require(
|
||||
healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD,
|
||||
Errors.TRANSFER_NOT_ALLOWED
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,13 +42,13 @@ library MathUtils {
|
|||
* @param lastUpdateTimestamp the timestamp of the last update of the interest
|
||||
* @return the interest rate compounded during the timeDelta, in ray
|
||||
**/
|
||||
function calculateCompoundedInterest(uint256 rate, uint40 lastUpdateTimestamp)
|
||||
internal
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
function calculateCompoundedInterest(
|
||||
uint256 rate,
|
||||
uint40 lastUpdateTimestamp,
|
||||
uint256 currentTimestamp
|
||||
) internal pure returns (uint256) {
|
||||
//solium-disable-next-line
|
||||
uint256 exp = block.timestamp.sub(uint256(lastUpdateTimestamp));
|
||||
uint256 exp = currentTimestamp.sub(uint256(lastUpdateTimestamp));
|
||||
|
||||
if (exp == 0) {
|
||||
return WadRayMath.ray();
|
||||
|
@ -68,4 +68,17 @@ library MathUtils {
|
|||
|
||||
return WadRayMath.ray().add(ratePerSecond.mul(exp)).add(secondTerm).add(thirdTerm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev calculates the compounded interest between the timestamp of the last update and the current block timestamp
|
||||
* @param rate the interest rate (in ray)
|
||||
* @param lastUpdateTimestamp the timestamp from which the interest accumulation needs to be calculated
|
||||
**/
|
||||
function calculateCompoundedInterest(uint256 rate, uint40 lastUpdateTimestamp)
|
||||
internal
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
return calculateCompoundedInterest(rate, lastUpdateTimestamp, block.timestamp);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,19 +22,16 @@ library PercentageMath {
|
|||
* @return the percentage of value
|
||||
**/
|
||||
function percentMul(uint256 value, uint256 percentage) internal pure returns (uint256) {
|
||||
if (value == 0) {
|
||||
if (value == 0 || percentage == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint256 result = value * percentage;
|
||||
require(
|
||||
value <= (type(uint256).max - HALF_PERCENT) / percentage,
|
||||
Errors.MULTIPLICATION_OVERFLOW
|
||||
);
|
||||
|
||||
require(result / value == percentage, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
result += HALF_PERCENT;
|
||||
|
||||
require(result >= HALF_PERCENT, Errors.ADDITION_OVERFLOW);
|
||||
|
||||
return result / PERCENTAGE_FACTOR;
|
||||
return (value * percentage + HALF_PERCENT) / PERCENTAGE_FACTOR;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,14 +44,11 @@ library PercentageMath {
|
|||
require(percentage != 0, Errors.DIVISION_BY_ZERO);
|
||||
uint256 halfPercentage = percentage / 2;
|
||||
|
||||
uint256 result = value * PERCENTAGE_FACTOR;
|
||||
require(
|
||||
value <= (type(uint256).max - halfPercentage) / PERCENTAGE_FACTOR,
|
||||
Errors.MULTIPLICATION_OVERFLOW
|
||||
);
|
||||
|
||||
require(result / PERCENTAGE_FACTOR == value, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
result += halfPercentage;
|
||||
|
||||
require(result >= halfPercentage, Errors.ADDITION_OVERFLOW);
|
||||
|
||||
return result / percentage;
|
||||
return (value * PERCENTAGE_FACTOR + halfPercentage) / percentage;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,15 +54,13 @@ library WadRayMath {
|
|||
* @return the result of a*b, in wad
|
||||
**/
|
||||
function wadMul(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
if (a == 0) {
|
||||
if (a == 0 || b == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint256 result = a * b + halfWAD;
|
||||
require(a <= (type(uint256).max - halfWAD) / b, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
require(result >= halfWAD && (result - halfWAD) / a == b, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
return result / WAD;
|
||||
return (a * b + halfWAD) / WAD;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,14 +71,11 @@ library WadRayMath {
|
|||
**/
|
||||
function wadDiv(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
require(b != 0, Errors.DIVISION_BY_ZERO);
|
||||
|
||||
uint256 halfB = b / 2;
|
||||
|
||||
uint256 result = a * WAD + halfB;
|
||||
require(a <= (type(uint256).max - halfB) / WAD, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
require(result >= halfB && (result - halfB) / WAD == a, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
return result / b;
|
||||
return (a * WAD + halfB) / b;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,15 +85,13 @@ library WadRayMath {
|
|||
* @return the result of a*b, in ray
|
||||
**/
|
||||
function rayMul(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
if (a == 0) {
|
||||
if (a == 0 || b == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint256 result = a * b + halfRAY;
|
||||
require(a <= (type(uint256).max - halfRAY) / b, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
require(result >= halfRAY && (result - halfRAY) / a == b, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
return result / RAY;
|
||||
return (a * b + halfRAY) / RAY;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,14 +102,11 @@ library WadRayMath {
|
|||
**/
|
||||
function rayDiv(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
require(b != 0, Errors.DIVISION_BY_ZERO);
|
||||
|
||||
uint256 halfB = b / 2;
|
||||
|
||||
uint256 result = a * RAY + halfB;
|
||||
require(a <= (type(uint256).max - halfB) / RAY, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
require(result >= halfB && (result - halfB) / RAY == a, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
return result / b;
|
||||
return (a * RAY + halfB) / b;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,7 @@ contract MintableERC20 is ERC20 {
|
|||
* @return A boolean that indicates if the operation was successful.
|
||||
*/
|
||||
function mint(uint256 value) public returns (bool) {
|
||||
_mint(msg.sender, value);
|
||||
_mint(_msgSender(), value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
|
|||
bytes32 public DOMAIN_SEPARATOR;
|
||||
|
||||
modifier onlyLendingPool {
|
||||
require(msg.sender == address(POOL), Errors.CALLER_MUST_BE_LENDING_POOL);
|
||||
require(_msgSender() == address(POOL), Errors.CALLER_MUST_BE_LENDING_POOL);
|
||||
_;
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
|
|||
|
||||
//transfer event to track balances
|
||||
emit Transfer(user, address(0), amount);
|
||||
emit Burn(msg.sender, receiverOfUnderlying, amount, index);
|
||||
emit Burn(_msgSender(), receiverOfUnderlying, amount, index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -241,16 +241,6 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
|
|||
return super.totalSupply();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Used to validate transfers before actually executing them.
|
||||
* @param user address of the user to check
|
||||
* @param amount the amount to check
|
||||
* @return true if the user can transfer amount, false otherwise
|
||||
**/
|
||||
function isTransferAllowed(address user, uint256 amount) public override view returns (bool) {
|
||||
return POOL.balanceDecreaseAllowed(UNDERLYING_ASSET_ADDRESS, user, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev transfers the underlying asset to the target. Used by the lendingpool to transfer
|
||||
* assets in borrow(), redeem() and flashLoan()
|
||||
|
@ -317,14 +307,24 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
|
|||
uint256 amount,
|
||||
bool validate
|
||||
) internal {
|
||||
if (validate) {
|
||||
require(isTransferAllowed(from, amount), Errors.TRANSFER_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
uint256 index = POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS);
|
||||
|
||||
uint256 fromBalanceBefore = super.balanceOf(from).rayMul(index);
|
||||
uint256 toBalanceBefore = super.balanceOf(to).rayMul(index);
|
||||
|
||||
super._transfer(from, to, amount.rayDiv(index));
|
||||
|
||||
if (validate) {
|
||||
POOL.finalizeTransfer(
|
||||
UNDERLYING_ASSET_ADDRESS,
|
||||
from,
|
||||
to,
|
||||
amount,
|
||||
fromBalanceBefore,
|
||||
toBalanceBefore
|
||||
);
|
||||
}
|
||||
|
||||
emit BalanceTransfer(from, to, amount, index);
|
||||
}
|
||||
|
||||
|
|
|
@ -73,14 +73,14 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
|
|||
}
|
||||
|
||||
/**
|
||||
* @dev executes a transfer of tokens from msg.sender to recipient
|
||||
* @dev executes a transfer of tokens from _msgSender() to recipient
|
||||
* @param recipient the recipient of the tokens
|
||||
* @param amount the amount of tokens being transferred
|
||||
* @return true if the transfer succeeds, false otherwise
|
||||
**/
|
||||
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
|
||||
_transfer(_msgSender(), recipient, amount);
|
||||
emit Transfer(msg.sender, recipient, amount);
|
||||
emit Transfer(_msgSender(), recipient, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -101,8 +101,8 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
|
|||
}
|
||||
|
||||
/**
|
||||
* @dev allows spender to spend the tokens owned by msg.sender
|
||||
* @param spender the user allowed to spend msg.sender tokens
|
||||
* @dev allows spender to spend the tokens owned by _msgSender()
|
||||
* @param spender the user allowed to spend _msgSender() tokens
|
||||
* @return true
|
||||
**/
|
||||
function approve(address spender, uint256 amount) public virtual override returns (bool) {
|
||||
|
@ -111,7 +111,7 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
|
|||
}
|
||||
|
||||
/**
|
||||
* @dev executes a transfer of token from sender to recipient, if msg.sender is allowed to do so
|
||||
* @dev executes a transfer of token from sender to recipient, if _msgSender() is allowed to do so
|
||||
* @param sender the owner of the tokens
|
||||
* @param recipient the recipient of the tokens
|
||||
* @param amount the amount of tokens being transferred
|
||||
|
@ -133,8 +133,8 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
|
|||
}
|
||||
|
||||
/**
|
||||
* @dev increases the allowance of spender to spend msg.sender tokens
|
||||
* @param spender the user allowed to spend on behalf of msg.sender
|
||||
* @dev increases the allowance of spender to spend _msgSender() tokens
|
||||
* @param spender the user allowed to spend on behalf of _msgSender()
|
||||
* @param addedValue the amount being added to the allowance
|
||||
* @return true
|
||||
**/
|
||||
|
@ -144,8 +144,8 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
|
|||
}
|
||||
|
||||
/**
|
||||
* @dev decreases the allowance of spender to spend msg.sender tokens
|
||||
* @param spender the user allowed to spend on behalf of msg.sender
|
||||
* @dev decreases the allowance of spender to spend _msgSender() tokens
|
||||
* @param spender the user allowed to spend on behalf of _msgSender()
|
||||
* @param subtractedValue the amount being subtracted to the allowance
|
||||
* @return true
|
||||
**/
|
||||
|
|
|
@ -23,7 +23,7 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
|
|||
* @dev Only lending pool can call functions marked by this modifier
|
||||
**/
|
||||
modifier onlyLendingPool {
|
||||
require(msg.sender == address(POOL), Errors.CALLER_MUST_BE_LENDING_POOL);
|
||||
require(_msgSender() == address(POOL), Errors.CALLER_MUST_BE_LENDING_POOL);
|
||||
_;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,8 +54,6 @@ interface IAToken is IERC20, IScaledBalanceToken {
|
|||
uint256 value
|
||||
) external;
|
||||
|
||||
function isTransferAllowed(address user, uint256 amount) external view returns (bool);
|
||||
|
||||
/**
|
||||
* @dev transfer the amount of the underlying asset to the user
|
||||
* @param user address of the user
|
||||
|
|
|
@ -3,303 +3,35 @@
|
|||
"buidlerevm": {
|
||||
"address": "0x58F132FBB86E21545A4Bace3C19f1C05d86d7A22",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xDFbeeed692AA81E7f86E72F7ACbEA2A1C4d63544",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x58F132FBB86E21545A4Bace3C19f1C05d86d7A22",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"LendingPoolAddressesProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0xa4bcDF64Cdd5451b6ac3743B414124A6299B65FF",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x5191aA68c7dB195181Dd2441dBE23A48EA24b040",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xa4bcDF64Cdd5451b6ac3743B414124A6299B65FF",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xF9a2E6D57c691f3aa5269858178a13Ef06378579",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"LendingPoolAddressesProviderRegistry": {
|
||||
"buidlerevm": {
|
||||
"address": "0x5A0773Ff307Bf7C71a832dBB5312237fD3437f9F",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xa89E20284Bd638F31b0011D0fC754Fc9d2fa73e3",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x5A0773Ff307Bf7C71a832dBB5312237fD3437f9F",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xf3266d89e6742fAE2C35D05eD549cd4e117300a7",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"FeeProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0xFAe0fd738dAbc8a0426F47437322b6d026A9FD95",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xD9273d497eDBC967F39d419461CfcF382a0A822e"
|
||||
}
|
||||
},
|
||||
"LendingPoolParametersProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0x2C4603396dE2F08642354A3A102760827FfFe113"
|
||||
}
|
||||
},
|
||||
"LendingPoolCore": {
|
||||
"buidlerevm": {
|
||||
"address": "0xA10958a24032283FbE2D23cedf264d6eC9411CBA"
|
||||
}
|
||||
},
|
||||
"LendingPoolConfigurator": {
|
||||
"buidlerevm": {
|
||||
"address": "0x6642B57e4265BAD868C17Fc1d1F4F88DBBA04Aa8"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x9Ec55627757348b322c8dD0865D704649bFa0c7b"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x1aae278bCcdb95817c7A546d752fC662F09b6DBa"
|
||||
}
|
||||
},
|
||||
"LendingPoolDataProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0x612719Ace03A8281188d61612A9f40D1da3ca420"
|
||||
}
|
||||
},
|
||||
"LendingPool": {
|
||||
"buidlerevm": {
|
||||
"address": "0xD9273d497eDBC967F39d419461CfcF382a0A822e"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x3EE716e38f21e5FC16BFDB773db24D63C637A5d8"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x8E05A3054cb736258FaF4638D07058cE6e294d2C"
|
||||
}
|
||||
},
|
||||
"PriceOracle": {
|
||||
"buidlerevm": {
|
||||
"address": "0x1750499D05Ed1674d822430FB960d5F6731fDf64",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x5889354f21A1C8D8D2f82669d778f6Dab778B519",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x1750499D05Ed1674d822430FB960d5F6731fDf64",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockAggregator": {
|
||||
"buidlerevm": {
|
||||
"address": "0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xC452C5244F701108B4e8E8BCe693160046b30332",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"ChainlinkProxyPriceProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0x7B6C3e5486D9e6959441ab554A889099eed76290",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x0B63c002cb44B2e5e580C3B3560a27F4101D95c0",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x7B6C3e5486D9e6959441ab554A889099eed76290",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x18a107d4fa249Efefd4DAf9A76EEE3b6366701AA",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"LendingRateOracle": {
|
||||
"buidlerevm": {
|
||||
"address": "0xD83D2773a7873ae2b5f8Fb92097e20a8C64F691E",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xCeB290A2C6614BF23B2faa0f0B8067F29C48DB0F",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xD83D2773a7873ae2b5f8Fb92097e20a8C64F691E",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xac6Eb7B1083D39eC695a3898C2f782E7c7C64973",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"DefaultReserveInterestRateStrategy": {
|
||||
"buidlerevm": {
|
||||
"address": "0xB660Fdd109a95718cB9d20E3A89EE6cE342aDcB6",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x7C95b1ad025F0C9aB14192f87bF2aD53889bE4F7",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x626FdE749F9d499d3777320CAf29484B624ab84a",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x47341CE48FfE1cbD91991578B880a18c45cdB5CA",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"LendingPoolLiquidationManager": {
|
||||
"buidlerevm": {
|
||||
"address": "0xFe230c227D3724015d0dE3dBEc831825f1ed1f59",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockOneSplit": {
|
||||
"buidlerevm": {
|
||||
"address": "0x4b2c297ba5be42610994974b9543D56B864CA011",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x4b2c297ba5be42610994974b9543D56B864CA011",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"OneSplitAdapter": {
|
||||
"buidlerevm": {
|
||||
"address": "0x24E420B42971372F060a93129846761F354Bc50B",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x24E420B42971372F060a93129846761F354Bc50B",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"TokenDistributor": {
|
||||
"buidlerevm": {
|
||||
"address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4"
|
||||
}
|
||||
},
|
||||
"InitializableAdminUpgradeabilityProxy": {
|
||||
"buidlerevm": {
|
||||
"address": "0xC6bA6049F86d528698B5924B8fC2FE7289D38578",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockFlashLoanReceiver": {
|
||||
"buidlerevm": {
|
||||
"address": "0xBEF0d4b9c089a5883741fC14cbA352055f35DDA2"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x9c91aEaD98b1354C7B0EAfb8ff539d0796c79894"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x2B681757d757fbB80cc51c6094cEF5eE75bF55aA"
|
||||
}
|
||||
},
|
||||
"WalletBalanceProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x145b7B6368Df63e7F3497b0A948B30fC1A4d5E55",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"DAI": {
|
||||
"buidlerevm": {
|
||||
"address": "0x7c2C195CD6D34B8F845992d380aADB2730bB9C6F",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x010e948B9B7D30771E23346C0B17a4D5Ff04e300",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x7c2C195CD6D34B8F845992d380aADB2730bB9C6F",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"LEND": {
|
||||
"buidlerevm": {
|
||||
"address": "0x8858eeB3DfffA017D4BCE9801D340D36Cf895CCf",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x79094eDB848047e87a4B8a64ab5Ee2f527791bC0",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x8858eeB3DfffA017D4BCE9801D340D36Cf895CCf",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"TUSD": {
|
||||
"buidlerevm": {
|
||||
"address": "0x0078371BDeDE8aAc7DeBfFf451B74c5EDB385Af7",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xEE0A69d0Bb1312685870Dd7E20AcAD66b6f6264F",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x0078371BDeDE8aAc7DeBfFf451B74c5EDB385Af7",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"BAT": {
|
||||
"buidlerevm": {
|
||||
"address": "0xf4e77E5Da47AC3125140c470c71cBca77B5c638c",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x631B367fBE1dbB934bC039aAA0C9eC2EE5943fd5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xf4e77E5Da47AC3125140c470c71cBca77B5c638c",
|
||||
}
|
||||
},
|
||||
"WETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0xf784709d2317D872237C4bC22f867d1BAe2913AB",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
|
@ -307,261 +39,119 @@
|
|||
"buidlerevm": {
|
||||
"address": "0x3619DbE27d7c1e7E91aA738697Ae7Bc5FC3eACA5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xf55Af78B3f3059fACF166Aa338FFe059A14e75F6",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x3619DbE27d7c1e7E91aA738697Ae7Bc5FC3eACA5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"USDT": {
|
||||
"buidlerevm": {
|
||||
"address": "0x038B86d9d8FAFdd0a02ebd1A476432877b0107C8",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xD5A0587aAEB195028909E98930B391dFB3f9F589",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x038B86d9d8FAFdd0a02ebd1A476432877b0107C8",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"SUSD": {
|
||||
"buidlerevm": {
|
||||
"address": "0x1A1FEe7EeD918BD762173e4dc5EfDB8a78C924A8",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xaD3AdbC18E4AD090034A6C74Eda61f4310dce313",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x1A1FEe7EeD918BD762173e4dc5EfDB8a78C924A8",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"ZRX": {
|
||||
"buidlerevm": {
|
||||
"address": "0x500D1d6A4c7D8Ae28240b47c8FCde034D827fD5e",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x25a88BbA9c8D2a46e3Ff4bFe98712DF7A1044fB6",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x500D1d6A4c7D8Ae28240b47c8FCde034D827fD5e",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MKR": {
|
||||
"buidlerevm": {
|
||||
"address": "0xc4905364b78a742ccce7B890A89514061E47068D",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x16d1802cd7cfcb67955BBBa26bAae1cE559B5F5B",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xc4905364b78a742ccce7B890A89514061E47068D",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"WBTC": {
|
||||
"buidlerevm": {
|
||||
"address": "0xD6C850aeBFDC46D7F4c207e445cC0d6B0919BDBe",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xE58d8c88f5A670f16BE8F7864707170F43e943A6",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xD6C850aeBFDC46D7F4c207e445cC0d6B0919BDBe",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"LINK": {
|
||||
"buidlerevm": {
|
||||
"address": "0x8B5B7a6055E54a36fF574bbE40cf2eA68d5554b3",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xfdAF4f6e47e854c05bE158993d32872e784F0502",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x8B5B7a6055E54a36fF574bbE40cf2eA68d5554b3",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"KNC": {
|
||||
"buidlerevm": {
|
||||
"address": "0xEcc0a6dbC0bb4D51E4F84A315a9e5B0438cAD4f0",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x92edC13A10036A3C50396f2B63148a3e9a8D589e",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xEcc0a6dbC0bb4D51E4F84A315a9e5B0438cAD4f0",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MANA": {
|
||||
"buidlerevm": {
|
||||
"address": "0x20Ce94F404343aD2752A2D01b43fa407db9E0D00",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xE5C277cDb7E10372918Ac54Ce54022910A24FE88",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x20Ce94F404343aD2752A2D01b43fa407db9E0D00",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"REP": {
|
||||
"buidlerevm": {
|
||||
"address": "0x1d80315fac6aBd3EfeEbE97dEc44461ba7556160",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xF5742a599a0F4520089cbf2EBBa66Bb4F471B85F",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x1d80315fac6aBd3EfeEbE97dEc44461ba7556160",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"SNX": {
|
||||
"buidlerevm": {
|
||||
"address": "0x2D8553F9ddA85A9B3259F6Bf26911364B85556F5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x380EF388e13D8cAdeACef6eF682C7B7D85865076",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x2D8553F9ddA85A9B3259F6Bf26911364B85556F5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"BUSD": {
|
||||
"buidlerevm": {
|
||||
"address": "0x52d3b94181f8654db2530b0fEe1B19173f519C52",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xC89577DED8441e52C17C13D527b85b225C5c8311",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x52d3b94181f8654db2530b0fEe1B19173f519C52",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"USD": {
|
||||
"buidlerevm": {
|
||||
"address": "0xd15468525c35BDBC1eD8F2e09A00F8a173437f2f",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xD4b06774A717Ff5A7c20c8712e31c6BbfFcb1F01",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xd15468525c35BDBC1eD8F2e09A00F8a173437f2f",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI_DAI_ETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0x7e35Eaf7e8FBd7887ad538D4A38Df5BbD073814a",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xbe66dC9DFEe580ED968403e35dF7b5159f873df8",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x7e35Eaf7e8FBd7887ad538D4A38Df5BbD073814a",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI_USDC_ETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0x5bcb88A0d20426e451332eE6C4324b0e663c50E0",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x93AfC6Df4bB8F62F2493B19e577f8382c0BA9EBC",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x5bcb88A0d20426e451332eE6C4324b0e663c50E0",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI_SETH_ETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0x3521eF8AaB0323004A6dD8b03CE890F4Ea3A13f5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x75Ded61646B5945BdDd0CD9a9Db7c8288DA6F810",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x3521eF8AaB0323004A6dD8b03CE890F4Ea3A13f5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI_LINK_ETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0x53369fd4680FfE3DfF39Fc6DDa9CfbfD43daeA2E",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xdE7c40e675bF1aA45c18cCbaEb9662B16b0Ddf7E",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x53369fd4680FfE3DfF39Fc6DDa9CfbfD43daeA2E",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI_MKR_ETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0xB00cC45B4a7d3e1FEE684cFc4417998A1c183e6d",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xEcb928A3c079a1696Aa5244779eEc3dE1717fACd",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xB00cC45B4a7d3e1FEE684cFc4417998A1c183e6d",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI_LEND_ETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0x58F132FBB86E21545A4Bace3C19f1C05d86d7A22",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xDFbeeed692AA81E7f86E72F7ACbEA2A1C4d63544",
|
||||
}
|
||||
},
|
||||
"LendingPoolAddressesProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0xa4bcDF64Cdd5451b6ac3743B414124A6299B65FF",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
|
@ -571,159 +161,108 @@
|
|||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"ReserveLogic": {
|
||||
"buidlerevm": {
|
||||
"address": "0xFAe0fd738dAbc8a0426F47437322b6d026A9FD95",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"GenericLogic": {
|
||||
"buidlerevm": {
|
||||
"address": "0x6082731fdAba4761277Fb31299ebC782AD3bCf24",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"ValidationLogic": {
|
||||
"buidlerevm": {
|
||||
"address": "0x8456161947DFc1fC159A0B26c025cD2b4bba0c3e",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"LendingPool": {
|
||||
"buidlerevm": {
|
||||
"address": "0xe7536f450378748E1BD4645D3c77ec38e0F3ba28"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x987223924D2DD6c6efB601756850f3886ECbceF6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xfF28b837352d9531bAb6dFF3650D7831192117F7",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
"address": "0xD9273d497eDBC967F39d419461CfcF382a0A822e"
|
||||
}
|
||||
},
|
||||
"LendingPoolConfigurator": {
|
||||
"buidlerevm": {
|
||||
"address": "0x830bceA96E56DBC1F8578f75fBaC0AF16B32A07d",
|
||||
"address": "0x6642B57e4265BAD868C17Fc1d1F4F88DBBA04Aa8"
|
||||
}
|
||||
},
|
||||
"StableAndVariableTokensHelper": {
|
||||
"buidlerevm": {
|
||||
"address": "0x0C6c3C47A1f650809B0D1048FDf9603e09473D7E",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xaca5aCeB6f44845d07Fd339a51F0bd52Bb3D8D1A",
|
||||
}
|
||||
},
|
||||
"ATokensAndRatesHelper": {
|
||||
"buidlerevm": {
|
||||
"address": "0x06bA8d8af0dF898D0712DffFb0f862cC51AF45c2",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xB660Fdd109a95718cB9d20E3A89EE6cE342aDcB6",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x0EDc241FdA0dF39EB1B9eB1236217BBe72Ab911D",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"PriceOracle": {
|
||||
"buidlerevm": {
|
||||
"address": "0x1750499D05Ed1674d822430FB960d5F6731fDf64",
|
||||
"address": "0xb682dEEf4f8e298d86bFc3e21f50c675151FB974",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x9bD0Bec44106D8Ea8fFb6296d7A84742a290E064",
|
||||
}
|
||||
},
|
||||
"MockAggregator": {
|
||||
"buidlerevm": {
|
||||
"address": "0x3D8FFB457fedDFBc760F3F243283F52692b579B1",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"ChainlinkProxyPriceProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0x7B6C3e5486D9e6959441ab554A889099eed76290",
|
||||
"address": "0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x293f5BcC66762c28a5d3Bd8512a799D457F5296D",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"AToken": {
|
||||
"localhost": {
|
||||
"address": "0x00f126cCA2266bFb634Ed6DB17c4C74fb8cA5177",
|
||||
"LendingRateOracle": {
|
||||
"buidlerevm": {
|
||||
"address": "0xAF6BA11790D1942625C0c2dA07da19AB63845cfF",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"AaveProtocolTestHelpers": {
|
||||
"buidlerevm": {
|
||||
"address": "0x689d0586F88cDEa1E1003F838DD943415E4EB1e5"
|
||||
"address": "0xf4830d6b1D70C8595d3BD8A63f9ed9F636DB9ef2"
|
||||
}
|
||||
},
|
||||
"DefaultReserveInterestRateStrategy": {
|
||||
"LendingPoolCollateralManager": {
|
||||
"buidlerevm": {
|
||||
"address": "0x5f7134cd38C826a7649f9Cc47dda24d834DD2967",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xA0AB1cB92A4AF81f84dCd258155B5c25D247b54E",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xf303Ae6F24C29D94E367fdb5C7aE04D32BEbF13E",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
}
|
||||
},
|
||||
"StableDebtToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0x3bDA11B584dDff7F66E0cFe1da1562c92B45db60",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xbF538F34cb100bAeEE55aa1F036D33F03b03d900",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x392E5355a0e88Bd394F717227c752670fb3a8020",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"VariableDebtToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0xf784709d2317D872237C4bC22f867d1BAe2913AB",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xff1B1B810F5DCe853a9b1819DE220D532D1CFeF2",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xf784709d2317D872237C4bC22f867d1BAe2913AB",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"AToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0x392E5355a0e88Bd394F717227c752670fb3a8020",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x7436d6adaA697413F00cb63E1A2A854bF2Aec5A1",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460",
|
||||
"address": "0x8D0206fEBEB380486729b64bB4cfEDC5b354a6D6",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockFlashLoanReceiver": {
|
||||
"buidlerevm": {
|
||||
"address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x2A7BE996B8801ED21f2f45148791D402811A2106",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xEBAB67ee3ef604D5c250A53b4b8fcbBC6ec3007C",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
"address": "0xfC88832bac6AbdF216BC5A67be68E9DE94aD5ba2"
|
||||
}
|
||||
},
|
||||
"WalletBalanceProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10"
|
||||
},
|
||||
"coverage": {
|
||||
"address": "0xBEF0d4b9c089a5883741fC14cbA352055f35DDA2"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0x48FAde2E719B770E1783d03466dAEe98b5183538"
|
||||
"address": "0x1256eBA4d0a7A38D10BaF4F61775ba491Ce7EE25",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockFlashRepayAdapter": {
|
||||
"MockAToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10"
|
||||
"address": "0x77B0b5636fEA30eA79BB65AeCCdb599997A849A8",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockFlashLiquiditySwapAdapter": {
|
||||
"MockStableDebtToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4"
|
||||
"address": "0x78Ee8Fb9fE5abD5e347Fc94c2fb85596d1f60e3c",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockVariableDebtToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0x920d847fE49E54C19047ba8bc236C45A8068Bca7",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
376
helpers/contracts-deployments.ts
Normal file
376
helpers/contracts-deployments.ts
Normal file
|
@ -0,0 +1,376 @@
|
|||
import {Contract} from 'ethers';
|
||||
import {BRE} from './misc-utils';
|
||||
import {
|
||||
tEthereumAddress,
|
||||
eContractid,
|
||||
tStringTokenSmallUnits,
|
||||
AavePools,
|
||||
TokenContractId,
|
||||
iMultiPoolsAssets,
|
||||
IReserveParams,
|
||||
PoolConfiguration,
|
||||
} from './types';
|
||||
|
||||
import {MintableErc20 as MintableERC20} from '../types/MintableErc20';
|
||||
import {readArtifact} from '@nomiclabs/buidler/plugins';
|
||||
import {MockContract} from 'ethereum-waffle';
|
||||
import {getReservesConfigByPool} from './configuration';
|
||||
import {getFirstSigner} from './contracts-getters';
|
||||
import {ZERO_ADDRESS} from './constants';
|
||||
import {
|
||||
AaveProtocolTestHelpersFactory,
|
||||
ATokenFactory,
|
||||
ATokensAndRatesHelperFactory,
|
||||
ChainlinkProxyPriceProviderFactory,
|
||||
DefaultReserveInterestRateStrategyFactory,
|
||||
InitializableAdminUpgradeabilityProxyFactory,
|
||||
LendingPoolAddressesProviderFactory,
|
||||
LendingPoolAddressesProviderRegistryFactory,
|
||||
LendingPoolCollateralManagerFactory,
|
||||
LendingPoolConfiguratorFactory,
|
||||
LendingPoolFactory,
|
||||
LendingPoolLibraryAddresses,
|
||||
LendingRateOracleFactory,
|
||||
MintableErc20Factory,
|
||||
MockAggregatorFactory,
|
||||
MockFlashLoanReceiverFactory,
|
||||
PriceOracleFactory,
|
||||
ReserveLogicFactory,
|
||||
StableDebtTokenFactory,
|
||||
VariableDebtTokenFactory,
|
||||
WalletBalanceProviderFactory,
|
||||
} from '../types';
|
||||
import {withSaveAndVerify, registerContractInJsonDb, linkBytecode} from './contracts-helpers';
|
||||
import {StableAndVariableTokensHelperFactory} from '../types/StableAndVariableTokensHelperFactory';
|
||||
|
||||
export const deployLendingPoolAddressesProvider = async (verify?: boolean) =>
|
||||
withSaveAndVerify(
|
||||
await new LendingPoolAddressesProviderFactory(await getFirstSigner()).deploy(),
|
||||
eContractid.LendingPoolAddressesProvider,
|
||||
[],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployLendingPoolAddressesProviderRegistry = async (verify?: boolean) =>
|
||||
withSaveAndVerify(
|
||||
await new LendingPoolAddressesProviderRegistryFactory(await getFirstSigner()).deploy(),
|
||||
eContractid.LendingPoolAddressesProviderRegistry,
|
||||
[],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployLendingPoolConfigurator = async (verify?: boolean) =>
|
||||
withSaveAndVerify(
|
||||
await new LendingPoolConfiguratorFactory(await getFirstSigner()).deploy(),
|
||||
eContractid.LendingPoolConfigurator,
|
||||
[],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployReserveLogicLibrary = async (verify?: boolean) =>
|
||||
withSaveAndVerify(
|
||||
await new ReserveLogicFactory(await getFirstSigner()).deploy(),
|
||||
eContractid.ReserveLogic,
|
||||
[],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployGenericLogic = async (reserveLogic: Contract, verify?: boolean) => {
|
||||
const genericLogicArtifact = await readArtifact(
|
||||
BRE.config.paths.artifacts,
|
||||
eContractid.GenericLogic
|
||||
);
|
||||
|
||||
const linkedGenericLogicByteCode = linkBytecode(genericLogicArtifact, {
|
||||
[eContractid.ReserveLogic]: reserveLogic.address,
|
||||
});
|
||||
|
||||
const genericLogicFactory = await BRE.ethers.getContractFactory(
|
||||
genericLogicArtifact.abi,
|
||||
linkedGenericLogicByteCode
|
||||
);
|
||||
|
||||
const genericLogic = await (await genericLogicFactory.deploy()).deployed();
|
||||
return withSaveAndVerify(genericLogic, eContractid.GenericLogic, [], verify);
|
||||
};
|
||||
|
||||
export const deployValidationLogic = async (
|
||||
reserveLogic: Contract,
|
||||
genericLogic: Contract,
|
||||
verify?: boolean
|
||||
) => {
|
||||
const validationLogicArtifact = await readArtifact(
|
||||
BRE.config.paths.artifacts,
|
||||
eContractid.ValidationLogic
|
||||
);
|
||||
|
||||
const linkedValidationLogicByteCode = linkBytecode(validationLogicArtifact, {
|
||||
[eContractid.ReserveLogic]: reserveLogic.address,
|
||||
[eContractid.GenericLogic]: genericLogic.address,
|
||||
});
|
||||
|
||||
const validationLogicFactory = await BRE.ethers.getContractFactory(
|
||||
validationLogicArtifact.abi,
|
||||
linkedValidationLogicByteCode
|
||||
);
|
||||
|
||||
const validationLogic = await (await validationLogicFactory.deploy()).deployed();
|
||||
|
||||
return withSaveAndVerify(validationLogic, eContractid.ValidationLogic, [], verify);
|
||||
};
|
||||
|
||||
export const deployAaveLibraries = async (
|
||||
verify?: boolean
|
||||
): Promise<LendingPoolLibraryAddresses> => {
|
||||
const reserveLogic = await deployReserveLogicLibrary(verify);
|
||||
const genericLogic = await deployGenericLogic(reserveLogic, verify);
|
||||
const validationLogic = await deployValidationLogic(reserveLogic, genericLogic, verify);
|
||||
|
||||
// Hardcoded solidity placeholders, if any library changes path this will fail.
|
||||
// The '__$PLACEHOLDER$__ can be calculated via solidity keccak, but the LendingPoolLibraryAddresses Type seems to
|
||||
// require a hardcoded string.
|
||||
//
|
||||
// how-to:
|
||||
// 1. PLACEHOLDER = solidityKeccak256(['string'], `${libPath}:${libName}`).slice(2, 36)
|
||||
// 2. LIB_PLACEHOLDER = `__$${PLACEHOLDER}$__`
|
||||
// or grab placeholdes from LendingPoolLibraryAddresses at Typechain generation.
|
||||
//
|
||||
// libPath example: contracts/libraries/logic/GenericLogic.sol
|
||||
// libName example: GenericLogic
|
||||
return {
|
||||
['__$5201a97c05ba6aa659e2f36a933dd51801$__']: validationLogic.address,
|
||||
['__$d3b4366daeb9cadc7528af6145b50b2183$__']: reserveLogic.address,
|
||||
['__$4c26be947d349222af871a3168b3fe584b$__']: genericLogic.address,
|
||||
};
|
||||
};
|
||||
|
||||
export const deployLendingPool = async (verify?: boolean) => {
|
||||
const libraries = await deployAaveLibraries(verify);
|
||||
return withSaveAndVerify(
|
||||
await new LendingPoolFactory(libraries, await getFirstSigner()).deploy(),
|
||||
eContractid.LendingPool,
|
||||
[],
|
||||
verify
|
||||
);
|
||||
};
|
||||
|
||||
export const deployPriceOracle = async (verify?: boolean) =>
|
||||
withSaveAndVerify(
|
||||
await new PriceOracleFactory(await getFirstSigner()).deploy(),
|
||||
eContractid.PriceOracle,
|
||||
[],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployLendingRateOracle = async (verify?: boolean) =>
|
||||
withSaveAndVerify(
|
||||
await new LendingRateOracleFactory(await getFirstSigner()).deploy(),
|
||||
eContractid.LendingRateOracle,
|
||||
[],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployMockAggregator = async (price: tStringTokenSmallUnits, verify?: boolean) =>
|
||||
withSaveAndVerify(
|
||||
await new MockAggregatorFactory(await getFirstSigner()).deploy(price),
|
||||
eContractid.MockAggregator,
|
||||
[price],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployChainlinkProxyPriceProvider = async (
|
||||
args: [tEthereumAddress[], tEthereumAddress[], tEthereumAddress],
|
||||
verify?: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new ChainlinkProxyPriceProviderFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.ChainlinkProxyPriceProvider,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployLendingPoolCollateralManager = async (verify?: boolean) => {
|
||||
return withSaveAndVerify(
|
||||
await new LendingPoolCollateralManagerFactory(await getFirstSigner()).deploy(),
|
||||
eContractid.LendingPoolCollateralManager,
|
||||
[],
|
||||
verify
|
||||
);
|
||||
};
|
||||
|
||||
export const deployInitializableAdminUpgradeabilityProxy = async (verify?: boolean) =>
|
||||
withSaveAndVerify(
|
||||
await new InitializableAdminUpgradeabilityProxyFactory(await getFirstSigner()).deploy(),
|
||||
eContractid.InitializableAdminUpgradeabilityProxy,
|
||||
[],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployMockFlashLoanReceiver = async (
|
||||
addressesProvider: tEthereumAddress,
|
||||
verify?: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new MockFlashLoanReceiverFactory(await getFirstSigner()).deploy(addressesProvider),
|
||||
eContractid.MockFlashLoanReceiver,
|
||||
[addressesProvider],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployWalletBalancerProvider = async (
|
||||
addressesProvider: tEthereumAddress,
|
||||
verify?: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new WalletBalanceProviderFactory(await getFirstSigner()).deploy(addressesProvider),
|
||||
eContractid.WalletBalanceProvider,
|
||||
[addressesProvider],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployAaveProtocolTestHelpers = async (
|
||||
addressesProvider: tEthereumAddress,
|
||||
verify?: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new AaveProtocolTestHelpersFactory(await getFirstSigner()).deploy(addressesProvider),
|
||||
eContractid.AaveProtocolTestHelpers,
|
||||
[addressesProvider],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployMintableERC20 = async (
|
||||
args: [string, string, string],
|
||||
verify?: boolean
|
||||
): Promise<MintableERC20> =>
|
||||
withSaveAndVerify(
|
||||
await new MintableErc20Factory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.MintableERC20,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployDefaultReserveInterestRateStrategy = async (
|
||||
args: [tEthereumAddress, string, string, string, string, string],
|
||||
verify: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new DefaultReserveInterestRateStrategyFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.DefaultReserveInterestRateStrategy,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployStableDebtToken = async (
|
||||
args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress],
|
||||
verify: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new StableDebtTokenFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.StableDebtToken,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployVariableDebtToken = async (
|
||||
args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress],
|
||||
verify: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new VariableDebtTokenFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.VariableDebtToken,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployGenericAToken = async (
|
||||
[poolAddress, underlyingAssetAddress, name, symbol, incentivesController]: [
|
||||
tEthereumAddress,
|
||||
tEthereumAddress,
|
||||
string,
|
||||
string,
|
||||
tEthereumAddress
|
||||
],
|
||||
verify: boolean
|
||||
) => {
|
||||
const args: [
|
||||
tEthereumAddress,
|
||||
tEthereumAddress,
|
||||
tEthereumAddress,
|
||||
string,
|
||||
string,
|
||||
tEthereumAddress
|
||||
] = [poolAddress, underlyingAssetAddress, ZERO_ADDRESS, name, symbol, incentivesController];
|
||||
return withSaveAndVerify(
|
||||
await new ATokenFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.AToken,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
};
|
||||
|
||||
export const deployAllMockTokens = async (verify?: boolean) => {
|
||||
const tokens: {[symbol: string]: MockContract | MintableERC20} = {};
|
||||
|
||||
const protoConfigData = getReservesConfigByPool(AavePools.proto);
|
||||
const secondaryConfigData = getReservesConfigByPool(AavePools.secondary);
|
||||
|
||||
for (const tokenSymbol of Object.keys(TokenContractId)) {
|
||||
let decimals = '18';
|
||||
|
||||
let configData = (<any>protoConfigData)[tokenSymbol];
|
||||
|
||||
if (!configData) {
|
||||
configData = (<any>secondaryConfigData)[tokenSymbol];
|
||||
}
|
||||
|
||||
tokens[tokenSymbol] = await deployMintableERC20(
|
||||
[tokenSymbol, tokenSymbol, configData ? configData.reserveDecimals : decimals],
|
||||
verify
|
||||
);
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
|
||||
export const deployMockTokens = async (config: PoolConfiguration, verify?: boolean) => {
|
||||
const tokens: {[symbol: string]: MockContract | MintableERC20} = {};
|
||||
const defaultDecimals = 18;
|
||||
|
||||
const configData = config.ReservesConfig;
|
||||
|
||||
for (const tokenSymbol of Object.keys(config.ReserveSymbols)) {
|
||||
tokens[tokenSymbol] = await deployMintableERC20(
|
||||
[
|
||||
tokenSymbol,
|
||||
tokenSymbol,
|
||||
configData[tokenSymbol as keyof iMultiPoolsAssets<IReserveParams>].reserveDecimals ||
|
||||
defaultDecimals.toString(),
|
||||
],
|
||||
verify
|
||||
);
|
||||
await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]);
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
|
||||
export const deployStableAndVariableTokensHelper = async (
|
||||
args: [tEthereumAddress, tEthereumAddress],
|
||||
verify?: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new StableAndVariableTokensHelperFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.StableAndVariableTokensHelper,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployATokensAndRatesHelper = async (
|
||||
args: [tEthereumAddress, tEthereumAddress, tEthereumAddress],
|
||||
verify?: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new ATokensAndRatesHelperFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.ATokensAndRatesHelper,
|
||||
args,
|
||||
verify
|
||||
);
|
|
@ -0,0 +1,224 @@
|
|||
import {
|
||||
AaveProtocolTestHelpersFactory,
|
||||
ATokenFactory,
|
||||
ATokensAndRatesHelperFactory,
|
||||
DefaultReserveInterestRateStrategyFactory,
|
||||
GenericLogicFactory,
|
||||
LendingPoolAddressesProviderFactory,
|
||||
LendingPoolAddressesProviderRegistryFactory,
|
||||
LendingPoolConfiguratorFactory,
|
||||
LendingPoolFactory,
|
||||
LendingRateOracleFactory,
|
||||
MintableErc20Factory,
|
||||
MockFlashLoanReceiverFactory,
|
||||
PriceOracleFactory,
|
||||
ReserveLogicFactory,
|
||||
StableAndVariableTokensHelperFactory,
|
||||
StableDebtTokenFactory,
|
||||
VariableDebtTokenFactory,
|
||||
} from '../types';
|
||||
import {Ierc20DetailedFactory} from '../types/Ierc20DetailedFactory';
|
||||
import {MockTokenMap} from './contracts-helpers';
|
||||
import {BRE, getDb} from './misc-utils';
|
||||
import {eContractid, PoolConfiguration, tEthereumAddress, TokenContractId} from './types';
|
||||
|
||||
export const getFirstSigner = async () => (await BRE.ethers.getSigners())[0];
|
||||
|
||||
export const getLendingPoolAddressesProvider = async (address?: tEthereumAddress) =>
|
||||
await LendingPoolAddressesProviderFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.LendingPoolAddressesProvider}.${BRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getLendingPoolConfiguratorProxy = async (address?: tEthereumAddress) => {
|
||||
return await LendingPoolConfiguratorFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.LendingPoolConfigurator}.${BRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
};
|
||||
|
||||
export const getLendingPool = async (address?: tEthereumAddress) =>
|
||||
await LendingPoolFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.LendingPool}.${BRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getPriceOracle = async (address?: tEthereumAddress) =>
|
||||
await PriceOracleFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.PriceOracle}.${BRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getAToken = async (address?: tEthereumAddress) =>
|
||||
await ATokenFactory.connect(
|
||||
address || (await getDb().get(`${eContractid.AToken}.${BRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getStableDebtToken = async (address?: tEthereumAddress) =>
|
||||
await StableDebtTokenFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.StableDebtToken}.${BRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getVariableDebtToken = async (address?: tEthereumAddress) =>
|
||||
await VariableDebtTokenFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.VariableDebtToken}.${BRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getMintableErc20 = async (address: tEthereumAddress) =>
|
||||
await MintableErc20Factory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.MintableERC20}.${BRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getIErc20Detailed = async (address: tEthereumAddress) =>
|
||||
await Ierc20DetailedFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.IERC20Detailed}.${BRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getAaveProtocolTestHelpers = async (address?: tEthereumAddress) =>
|
||||
await AaveProtocolTestHelpersFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.AaveProtocolTestHelpers}.${BRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getInterestRateStrategy = async (address?: tEthereumAddress) =>
|
||||
await DefaultReserveInterestRateStrategyFactory.connect(
|
||||
address ||
|
||||
(
|
||||
await getDb()
|
||||
.get(`${eContractid.DefaultReserveInterestRateStrategy}.${BRE.network.name}`)
|
||||
.value()
|
||||
).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getMockFlashLoanReceiver = async (address?: tEthereumAddress) =>
|
||||
await MockFlashLoanReceiverFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.MockFlashLoanReceiver}.${BRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getLendingRateOracle = async (address?: tEthereumAddress) =>
|
||||
await LendingRateOracleFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.LendingRateOracle}.${BRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getMockedTokens = async (config: PoolConfiguration) => {
|
||||
const tokenSymbols = config.ReserveSymbols;
|
||||
const db = getDb();
|
||||
const tokens: MockTokenMap = await tokenSymbols.reduce<Promise<MockTokenMap>>(
|
||||
async (acc, tokenSymbol) => {
|
||||
const accumulator = await acc;
|
||||
const address = db.get(`${tokenSymbol.toUpperCase()}.${BRE.network.name}`).value().address;
|
||||
accumulator[tokenSymbol] = await getMintableErc20(address);
|
||||
return Promise.resolve(acc);
|
||||
},
|
||||
Promise.resolve({})
|
||||
);
|
||||
return tokens;
|
||||
};
|
||||
|
||||
export const getAllMockedTokens = async () => {
|
||||
const db = getDb();
|
||||
const tokens: MockTokenMap = await Object.keys(TokenContractId).reduce<Promise<MockTokenMap>>(
|
||||
async (acc, tokenSymbol) => {
|
||||
const accumulator = await acc;
|
||||
const address = db.get(`${tokenSymbol.toUpperCase()}.${BRE.network.name}`).value().address;
|
||||
accumulator[tokenSymbol] = await getMintableErc20(address);
|
||||
return Promise.resolve(acc);
|
||||
},
|
||||
Promise.resolve({})
|
||||
);
|
||||
return tokens;
|
||||
};
|
||||
|
||||
export const getPairsTokenAggregator = (
|
||||
allAssetsAddresses: {
|
||||
[tokenSymbol: string]: tEthereumAddress;
|
||||
},
|
||||
aggregatorsAddresses: {[tokenSymbol: string]: tEthereumAddress}
|
||||
): [string[], string[]] => {
|
||||
const {ETH, USD, WETH, ...assetsAddressesWithoutEth} = allAssetsAddresses;
|
||||
|
||||
const pairs = Object.entries(assetsAddressesWithoutEth).map(([tokenSymbol, tokenAddress]) => {
|
||||
if (tokenSymbol !== 'WETH' && tokenSymbol !== 'ETH') {
|
||||
const aggregatorAddressIndex = Object.keys(aggregatorsAddresses).findIndex(
|
||||
(value) => value === tokenSymbol
|
||||
);
|
||||
const [, aggregatorAddress] = (Object.entries(aggregatorsAddresses) as [
|
||||
string,
|
||||
tEthereumAddress
|
||||
][])[aggregatorAddressIndex];
|
||||
return [tokenAddress, aggregatorAddress];
|
||||
}
|
||||
}) as [string, string][];
|
||||
|
||||
const mappedPairs = pairs.map(([asset]) => asset);
|
||||
const mappedAggregators = pairs.map(([, source]) => source);
|
||||
|
||||
return [mappedPairs, mappedAggregators];
|
||||
};
|
||||
|
||||
export const getLendingPoolAddressesProviderRegistry = async (address?: tEthereumAddress) =>
|
||||
await LendingPoolAddressesProviderRegistryFactory.connect(
|
||||
address ||
|
||||
(
|
||||
await getDb()
|
||||
.get(`${eContractid.LendingPoolAddressesProviderRegistry}.${BRE.network.name}`)
|
||||
.value()
|
||||
).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getReserveLogic = async (address?: tEthereumAddress) =>
|
||||
await ReserveLogicFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.ReserveLogic}.${BRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getGenericLogic = async (address?: tEthereumAddress) =>
|
||||
await GenericLogicFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.GenericLogic}.${BRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getStableAndVariableTokensHelper = async (address?: tEthereumAddress) =>
|
||||
await StableAndVariableTokensHelperFactory.connect(
|
||||
address ||
|
||||
(
|
||||
await getDb()
|
||||
.get(`${eContractid.StableAndVariableTokensHelper}.${BRE.network.name}`)
|
||||
.value()
|
||||
).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getATokensAndRatesHelper = async (address?: tEthereumAddress) =>
|
||||
await ATokensAndRatesHelperFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.ATokensAndRatesHelper}.${BRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
|
@ -1,5 +1,7 @@
|
|||
import {Contract, Signer, utils, ethers} from 'ethers';
|
||||
import {CommonsConfig} from '../config/commons';
|
||||
import {signTypedData_v4} from 'eth-sig-util';
|
||||
import {fromRpcSig, ECDSASignature} from 'ethereumjs-util';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import {getDb, BRE, waitForTx} from './misc-utils';
|
||||
import {
|
||||
tEthereumAddress,
|
||||
|
@ -9,47 +11,13 @@ import {
|
|||
AavePools,
|
||||
iParamsPerNetwork,
|
||||
iParamsPerPool,
|
||||
TokenContractId,
|
||||
iMultiPoolsAssets,
|
||||
IReserveParams,
|
||||
ICommonConfiguration,
|
||||
PoolConfiguration,
|
||||
} from './types';
|
||||
|
||||
import {LendingPoolAddressesProvider} from '../types/LendingPoolAddressesProvider';
|
||||
import {MintableErc20 as MintableERC20} from '../types/MintableErc20';
|
||||
import {LendingPoolAddressesProviderRegistry} from '../types/LendingPoolAddressesProviderRegistry';
|
||||
import {LendingPoolConfigurator} from '../types/LendingPoolConfigurator';
|
||||
import {readArtifact} from '@nomiclabs/buidler/plugins';
|
||||
import {Artifact} from '@nomiclabs/buidler/types';
|
||||
import {LendingPool} from '../types/LendingPool';
|
||||
import {PriceOracle} from '../types/PriceOracle';
|
||||
import {MockAggregator} from '../types/MockAggregator';
|
||||
import {LendingRateOracle} from '../types/LendingRateOracle';
|
||||
import {DefaultReserveInterestRateStrategy} from '../types/DefaultReserveInterestRateStrategy';
|
||||
import {LendingPoolCollateralManager} from '../types/LendingPoolCollateralManager';
|
||||
import {InitializableAdminUpgradeabilityProxy} from '../types/InitializableAdminUpgradeabilityProxy';
|
||||
import {MockFlashLoanReceiver} from '../types/MockFlashLoanReceiver';
|
||||
import {WalletBalanceProvider} from '../types/WalletBalanceProvider';
|
||||
import {AToken} from '../types/AToken';
|
||||
import {AaveProtocolTestHelpers} from '../types/AaveProtocolTestHelpers';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import {Ierc20Detailed} from '../types/Ierc20Detailed';
|
||||
import {StableDebtToken} from '../types/StableDebtToken';
|
||||
import {VariableDebtToken} from '../types/VariableDebtToken';
|
||||
import {MockContract} from 'ethereum-waffle';
|
||||
import {getReservesConfigByPool} from './configuration';
|
||||
import {verifyContract} from './etherscan-verification';
|
||||
|
||||
const {
|
||||
ProtocolGlobalParams: {UsdAddress},
|
||||
} = CommonsConfig;
|
||||
import {getIErc20Detailed} from './contracts-getters';
|
||||
|
||||
export type MockTokenMap = {[symbol: string]: MintableERC20};
|
||||
import {ZERO_ADDRESS} from './constants';
|
||||
import {signTypedData_v4, TypedData} from 'eth-sig-util';
|
||||
import {fromRpcSig, ECDSASignature} from 'ethereumjs-util';
|
||||
import {SignerWithAddress} from '../test/helpers/make-suite';
|
||||
|
||||
export const registerContractInJsonDb = async (contractId: string, contractInstance: Contract) => {
|
||||
const currentNetwork = BRE.network.name;
|
||||
|
@ -105,456 +73,26 @@ export const deployContract = async <ContractType extends Contract>(
|
|||
return contract;
|
||||
};
|
||||
|
||||
export const withSaveAndVerify = async <ContractType extends Contract>(
|
||||
instance: ContractType,
|
||||
id: string,
|
||||
args: (string | string[])[],
|
||||
verify?: boolean
|
||||
): Promise<ContractType> => {
|
||||
await waitForTx(instance.deployTransaction);
|
||||
await registerContractInJsonDb(id, instance);
|
||||
if (verify) {
|
||||
await verifyContract(id, instance.address, args);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const getContract = async <ContractType extends Contract>(
|
||||
contractName: string,
|
||||
address: string
|
||||
): Promise<ContractType> => (await BRE.ethers.getContractAt(contractName, address)) as ContractType;
|
||||
|
||||
export const deployLendingPoolAddressesProvider = async (verify?: boolean) => {
|
||||
const instance = await deployContract<LendingPoolAddressesProvider>(
|
||||
eContractid.LendingPoolAddressesProvider,
|
||||
[]
|
||||
);
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.LendingPoolAddressesProvider, instance.address, []);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployLendingPoolAddressesProviderRegistry = async (verify?: boolean) => {
|
||||
const instance = await deployContract<LendingPoolAddressesProviderRegistry>(
|
||||
eContractid.LendingPoolAddressesProviderRegistry,
|
||||
[]
|
||||
);
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.LendingPoolAddressesProviderRegistry, instance.address, []);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployLendingPoolConfigurator = async (verify?: boolean) => {
|
||||
const instance = await deployContract<LendingPoolConfigurator>(
|
||||
eContractid.LendingPoolConfigurator,
|
||||
[]
|
||||
);
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.LendingPoolConfigurator, instance.address, []);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
const deployLibrary = async (libraryId: eContractid) => {
|
||||
const factory = await BRE.ethers.getContractFactory(libraryId);
|
||||
const library = await factory.deploy();
|
||||
await library.deployed();
|
||||
|
||||
return library;
|
||||
};
|
||||
|
||||
export const linkLibrariesToArtifact = async (artifact: Artifact) => {
|
||||
const reserveLogic = await deployLibrary(eContractid.ReserveLogic);
|
||||
|
||||
const genericLogicArtifact = await readArtifact(
|
||||
BRE.config.paths.artifacts,
|
||||
eContractid.GenericLogic
|
||||
);
|
||||
|
||||
const linkedGenericLogicByteCode = linkBytecode(genericLogicArtifact, {
|
||||
[eContractid.ReserveLogic]: reserveLogic.address,
|
||||
});
|
||||
|
||||
const genericLogicFactory = await BRE.ethers.getContractFactory(
|
||||
genericLogicArtifact.abi,
|
||||
linkedGenericLogicByteCode
|
||||
);
|
||||
|
||||
const genericLogic = await (await genericLogicFactory.deploy()).deployed();
|
||||
|
||||
const validationLogicArtifact = await readArtifact(
|
||||
BRE.config.paths.artifacts,
|
||||
eContractid.ValidationLogic
|
||||
);
|
||||
|
||||
const linkedValidationLogicByteCode = linkBytecode(validationLogicArtifact, {
|
||||
[eContractid.ReserveLogic]: reserveLogic.address,
|
||||
[eContractid.GenericLogic]: genericLogic.address,
|
||||
});
|
||||
|
||||
const validationLogicFactory = await BRE.ethers.getContractFactory(
|
||||
validationLogicArtifact.abi,
|
||||
linkedValidationLogicByteCode
|
||||
);
|
||||
|
||||
const validationLogic = await (await validationLogicFactory.deploy()).deployed();
|
||||
|
||||
const linkedBytecode = linkBytecode(artifact, {
|
||||
[eContractid.ReserveLogic]: reserveLogic.address,
|
||||
[eContractid.GenericLogic]: genericLogic.address,
|
||||
[eContractid.ValidationLogic]: validationLogic.address,
|
||||
});
|
||||
const factory = await BRE.ethers.getContractFactory(artifact.abi, linkedBytecode);
|
||||
|
||||
return factory;
|
||||
};
|
||||
|
||||
export const deployLendingPool = async (verify?: boolean) => {
|
||||
const lendingPoolArtifact = await readArtifact(
|
||||
BRE.config.paths.artifacts,
|
||||
eContractid.LendingPool
|
||||
);
|
||||
const factory = await linkLibrariesToArtifact(lendingPoolArtifact);
|
||||
const lendingPool = await factory.deploy();
|
||||
await waitForTx(lendingPool.deployTransaction);
|
||||
const instance = (await lendingPool.deployed()) as LendingPool;
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.LendingPool, instance.address, []);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployPriceOracle = async (verify?: boolean) => {
|
||||
const instance = await deployContract<PriceOracle>(eContractid.PriceOracle, []);
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.PriceOracle, instance.address, []);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployLendingRateOracle = async (verify?: boolean) => {
|
||||
const instance = await deployContract<LendingRateOracle>(eContractid.LendingRateOracle, []);
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.LendingRateOracle, instance.address, []);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployMockAggregator = async (price: tStringTokenSmallUnits, verify?: boolean) => {
|
||||
const args = [price];
|
||||
const instance = await deployContract<MockAggregator>(eContractid.MockAggregator, args);
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.MockAggregator, instance.address, args);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployChainlinkProxyPriceProvider = async (
|
||||
[assetsAddresses, sourcesAddresses, fallbackOracleAddress]: [
|
||||
tEthereumAddress[],
|
||||
tEthereumAddress[],
|
||||
tEthereumAddress
|
||||
],
|
||||
verify?: boolean
|
||||
) => {
|
||||
const args = [assetsAddresses, sourcesAddresses, fallbackOracleAddress];
|
||||
const instance = await deployContract<MockAggregator>(
|
||||
eContractid.ChainlinkProxyPriceProvider,
|
||||
args
|
||||
);
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.MockAggregator, instance.address, args);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const getChainlingProxyPriceProvider = async (address?: tEthereumAddress) =>
|
||||
await getContract<MockAggregator>(
|
||||
eContractid.ChainlinkProxyPriceProvider,
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.ChainlinkProxyPriceProvider}.${BRE.network.name}`).value())
|
||||
.address
|
||||
);
|
||||
|
||||
export const deployLendingPoolCollateralManager = async (verify?: boolean) => {
|
||||
const collateralManagerArtifact = await readArtifact(
|
||||
BRE.config.paths.artifacts,
|
||||
eContractid.LendingPoolCollateralManager
|
||||
);
|
||||
|
||||
const factory = await linkLibrariesToArtifact(collateralManagerArtifact);
|
||||
const args: string[] = [];
|
||||
const collateralManager = await factory.deploy(args);
|
||||
const instance = (await collateralManager.deployed()) as LendingPoolCollateralManager;
|
||||
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.LendingPoolCollateralManager, instance.address, args);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployInitializableAdminUpgradeabilityProxy = async (verify?: boolean) => {
|
||||
const instance = await deployContract<InitializableAdminUpgradeabilityProxy>(
|
||||
eContractid.InitializableAdminUpgradeabilityProxy,
|
||||
[]
|
||||
);
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.InitializableAdminUpgradeabilityProxy, instance.address, []);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployMockFlashLoanReceiver = async (
|
||||
addressesProvider: tEthereumAddress,
|
||||
verify?: boolean
|
||||
) => {
|
||||
const args = [addressesProvider];
|
||||
const instance = await deployContract<MockFlashLoanReceiver>(
|
||||
eContractid.MockFlashLoanReceiver,
|
||||
args
|
||||
);
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.MockFlashLoanReceiver, instance.address, args);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployWalletBalancerProvider = async (
|
||||
addressesProvider: tEthereumAddress,
|
||||
verify?: boolean
|
||||
) => {
|
||||
const args = [addressesProvider];
|
||||
const instance = await deployContract<WalletBalanceProvider>(
|
||||
eContractid.WalletBalanceProvider,
|
||||
args
|
||||
);
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.WalletBalanceProvider, instance.address, args);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployAaveProtocolTestHelpers = async (
|
||||
addressesProvider: tEthereumAddress,
|
||||
verify?: boolean
|
||||
) => {
|
||||
const args = [addressesProvider];
|
||||
const instance = await deployContract<AaveProtocolTestHelpers>(
|
||||
eContractid.AaveProtocolTestHelpers,
|
||||
args
|
||||
);
|
||||
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.AaveProtocolTestHelpers, instance.address, args);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployMintableERC20 = async ([name, symbol, decimals]: [string, string, number]) =>
|
||||
await deployContract<MintableERC20>(eContractid.MintableERC20, [name, symbol, decimals]);
|
||||
|
||||
export const deployDefaultReserveInterestRateStrategy = async (
|
||||
[
|
||||
addressesProvider,
|
||||
baseVariableBorrowRate,
|
||||
variableSlope1,
|
||||
variableSlope2,
|
||||
stableSlope1,
|
||||
stableSlope2,
|
||||
]: [tEthereumAddress, string, string, string, string, string],
|
||||
verify: boolean
|
||||
) => {
|
||||
const id = eContractid.DefaultReserveInterestRateStrategy;
|
||||
const args = [
|
||||
addressesProvider,
|
||||
baseVariableBorrowRate,
|
||||
variableSlope1,
|
||||
variableSlope2,
|
||||
stableSlope1,
|
||||
stableSlope2,
|
||||
];
|
||||
const instance = await deployContract<DefaultReserveInterestRateStrategy>(id, args);
|
||||
|
||||
if (verify) {
|
||||
await verifyContract(id, instance.address, args);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployStableDebtToken = async (
|
||||
[name, symbol, underlyingAsset, poolAddress, incentivesController]: [
|
||||
string,
|
||||
string,
|
||||
tEthereumAddress,
|
||||
tEthereumAddress,
|
||||
tEthereumAddress
|
||||
],
|
||||
verify: boolean
|
||||
) => {
|
||||
const id = eContractid.StableDebtToken;
|
||||
const args = [poolAddress, underlyingAsset, name, symbol, incentivesController];
|
||||
const instance = await deployContract<StableDebtToken>(id, args);
|
||||
|
||||
if (verify) {
|
||||
await verifyContract(id, instance.address, args);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployVariableDebtToken = async (
|
||||
[name, symbol, underlyingAsset, poolAddress, incentivesController]: [
|
||||
string,
|
||||
string,
|
||||
tEthereumAddress,
|
||||
tEthereumAddress,
|
||||
tEthereumAddress
|
||||
],
|
||||
verify: boolean
|
||||
) => {
|
||||
const id = eContractid.VariableDebtToken;
|
||||
const args = [poolAddress, underlyingAsset, name, symbol, incentivesController];
|
||||
const instance = await deployContract<VariableDebtToken>(id, args);
|
||||
|
||||
if (verify) {
|
||||
await verifyContract(id, instance.address, args);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const deployGenericAToken = async (
|
||||
[poolAddress, underlyingAssetAddress, name, symbol, incentivesController]: [
|
||||
tEthereumAddress,
|
||||
tEthereumAddress,
|
||||
string,
|
||||
string,
|
||||
tEthereumAddress
|
||||
],
|
||||
verify: boolean
|
||||
) => {
|
||||
const id = eContractid.AToken;
|
||||
const args = [
|
||||
poolAddress,
|
||||
underlyingAssetAddress,
|
||||
ZERO_ADDRESS,
|
||||
name,
|
||||
symbol,
|
||||
incentivesController,
|
||||
];
|
||||
const instance = await deployContract<AToken>(id, args);
|
||||
|
||||
if (verify) {
|
||||
await verifyContract(id, instance.address, args);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const getLendingPoolAddressesProvider = async (address?: tEthereumAddress) => {
|
||||
return await getContract<LendingPoolAddressesProvider>(
|
||||
eContractid.LendingPoolAddressesProvider,
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.LendingPoolAddressesProvider}.${BRE.network.name}`).value())
|
||||
.address
|
||||
);
|
||||
};
|
||||
|
||||
export const getLendingPoolConfiguratorProxy = async (address?: tEthereumAddress) => {
|
||||
return await getContract<LendingPoolConfigurator>(
|
||||
eContractid.LendingPoolConfigurator,
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.LendingPoolConfigurator}.${BRE.network.name}`).value())
|
||||
.address
|
||||
);
|
||||
};
|
||||
|
||||
export const getLendingPool = async (address?: tEthereumAddress) => {
|
||||
const lendingPoolArtifact = await readArtifact(
|
||||
BRE.config.paths.artifacts,
|
||||
eContractid.LendingPool
|
||||
);
|
||||
|
||||
const factory = await linkLibrariesToArtifact(lendingPoolArtifact);
|
||||
|
||||
return <LendingPool>(
|
||||
await factory.attach(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.LendingPool}.${BRE.network.name}`).value()).address
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export const getPriceOracle = async (address?: tEthereumAddress) => {
|
||||
return await getContract<PriceOracle>(
|
||||
eContractid.PriceOracle,
|
||||
address || (await getDb().get(`${eContractid.PriceOracle}.${BRE.network.name}`).value()).address
|
||||
);
|
||||
};
|
||||
|
||||
export const getAToken = async (address?: tEthereumAddress) => {
|
||||
return await getContract<AToken>(
|
||||
eContractid.AToken,
|
||||
address || (await getDb().get(`${eContractid.AToken}.${BRE.network.name}`).value()).address
|
||||
);
|
||||
};
|
||||
|
||||
export const getStableDebtToken = async (address?: tEthereumAddress) => {
|
||||
return await getContract<AToken>(
|
||||
eContractid.StableDebtToken,
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.StableDebtToken}.${BRE.network.name}`).value()).address
|
||||
);
|
||||
};
|
||||
|
||||
export const getVariableDebtToken = async (address?: tEthereumAddress) => {
|
||||
return await getContract<AToken>(
|
||||
eContractid.VariableDebtToken,
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.VariableDebtToken}.${BRE.network.name}`).value()).address
|
||||
);
|
||||
};
|
||||
|
||||
export const getMintableErc20 = async (address: tEthereumAddress) => {
|
||||
return await getContract<MintableERC20>(
|
||||
eContractid.MintableERC20,
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.MintableERC20}.${BRE.network.name}`).value()).address
|
||||
);
|
||||
};
|
||||
|
||||
export const getIErc20Detailed = async (address: tEthereumAddress) => {
|
||||
return await getContract<Ierc20Detailed>(
|
||||
eContractid.IERC20Detailed,
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.IERC20Detailed}.${BRE.network.name}`).value()).address
|
||||
);
|
||||
};
|
||||
|
||||
export const getAaveProtocolTestHelpers = async (address?: tEthereumAddress) => {
|
||||
return await getContract<AaveProtocolTestHelpers>(
|
||||
eContractid.AaveProtocolTestHelpers,
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.AaveProtocolTestHelpers}.${BRE.network.name}`).value())
|
||||
.address
|
||||
);
|
||||
};
|
||||
|
||||
export const getInterestRateStrategy = async (address?: tEthereumAddress) => {
|
||||
return await getContract<DefaultReserveInterestRateStrategy>(
|
||||
eContractid.DefaultReserveInterestRateStrategy,
|
||||
address ||
|
||||
(
|
||||
await getDb()
|
||||
.get(`${eContractid.DefaultReserveInterestRateStrategy}.${BRE.network.name}`)
|
||||
.value()
|
||||
).address
|
||||
);
|
||||
};
|
||||
|
||||
export const getMockFlashLoanReceiver = async (address?: tEthereumAddress) => {
|
||||
return await getContract<MockFlashLoanReceiver>(
|
||||
eContractid.MockFlashLoanReceiver,
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.MockFlashLoanReceiver}.${BRE.network.name}`).value())
|
||||
.address
|
||||
);
|
||||
};
|
||||
|
||||
export const getLendingRateOracle = async (address?: tEthereumAddress) => {
|
||||
return await getContract<LendingRateOracle>(
|
||||
eContractid.LendingRateOracle,
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.LendingRateOracle}.${BRE.network.name}`).value()).address
|
||||
);
|
||||
};
|
||||
|
||||
const linkBytecode = (artifact: Artifact, libraries: any) => {
|
||||
export const linkBytecode = (artifact: Artifact, libraries: any) => {
|
||||
let bytecode = artifact.bytecode;
|
||||
|
||||
for (const [fileName, fileReferences] of Object.entries(artifact.linkReferences)) {
|
||||
|
@ -623,254 +161,6 @@ export const convertToCurrencyUnits = async (tokenAddress: string, amount: strin
|
|||
return amountInCurrencyUnits.toFixed();
|
||||
};
|
||||
|
||||
export const deployAllMockTokens = async (verify?: boolean) => {
|
||||
const tokens: {[symbol: string]: MockContract | MintableERC20} = {};
|
||||
|
||||
const protoConfigData = getReservesConfigByPool(AavePools.proto);
|
||||
const secondaryConfigData = getReservesConfigByPool(AavePools.secondary);
|
||||
|
||||
for (const tokenSymbol of Object.keys(TokenContractId)) {
|
||||
let decimals = 18;
|
||||
|
||||
let configData = (<any>protoConfigData)[tokenSymbol];
|
||||
|
||||
if (!configData) {
|
||||
configData = (<any>secondaryConfigData)[tokenSymbol];
|
||||
}
|
||||
|
||||
if (!configData) {
|
||||
decimals = 18;
|
||||
}
|
||||
|
||||
tokens[tokenSymbol] = await deployMintableERC20([
|
||||
tokenSymbol,
|
||||
tokenSymbol,
|
||||
configData ? configData.reserveDecimals : 18,
|
||||
]);
|
||||
await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]);
|
||||
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.MintableERC20, tokens[tokenSymbol].address, []);
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
|
||||
export const deployMockTokens = async (config: PoolConfiguration, verify?: boolean) => {
|
||||
const tokens: {[symbol: string]: MockContract | MintableERC20} = {};
|
||||
const defaultDecimals = 18;
|
||||
|
||||
const configData = config.ReservesConfig;
|
||||
|
||||
for (const tokenSymbol of Object.keys(config.ReserveSymbols)) {
|
||||
tokens[tokenSymbol] = await deployMintableERC20([
|
||||
tokenSymbol,
|
||||
tokenSymbol,
|
||||
Number(configData[tokenSymbol as keyof iMultiPoolsAssets<IReserveParams>].reserveDecimals) ||
|
||||
defaultDecimals,
|
||||
]);
|
||||
await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]);
|
||||
|
||||
if (verify) {
|
||||
await verifyContract(eContractid.MintableERC20, tokens[tokenSymbol].address, []);
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
|
||||
export const getMockedTokens = async (config: PoolConfiguration) => {
|
||||
const tokenSymbols = config.ReserveSymbols;
|
||||
const db = getDb();
|
||||
const tokens: MockTokenMap = await tokenSymbols.reduce<Promise<MockTokenMap>>(
|
||||
async (acc, tokenSymbol) => {
|
||||
const accumulator = await acc;
|
||||
const address = db.get(`${tokenSymbol.toUpperCase()}.${BRE.network.name}`).value().address;
|
||||
accumulator[tokenSymbol] = await getContract<MintableERC20>(
|
||||
eContractid.MintableERC20,
|
||||
address
|
||||
);
|
||||
return Promise.resolve(acc);
|
||||
},
|
||||
Promise.resolve({})
|
||||
);
|
||||
return tokens;
|
||||
};
|
||||
|
||||
export const getAllMockedTokens = async () => {
|
||||
const db = getDb();
|
||||
const tokens: MockTokenMap = await Object.keys(TokenContractId).reduce<Promise<MockTokenMap>>(
|
||||
async (acc, tokenSymbol) => {
|
||||
const accumulator = await acc;
|
||||
const address = db.get(`${tokenSymbol.toUpperCase()}.${BRE.network.name}`).value().address;
|
||||
accumulator[tokenSymbol] = await getContract<MintableERC20>(
|
||||
eContractid.MintableERC20,
|
||||
address
|
||||
);
|
||||
return Promise.resolve(acc);
|
||||
},
|
||||
Promise.resolve({})
|
||||
);
|
||||
return tokens;
|
||||
};
|
||||
|
||||
export const getPairsTokenAggregator = (
|
||||
allAssetsAddresses: {
|
||||
[tokenSymbol: string]: tEthereumAddress;
|
||||
},
|
||||
aggregatorsAddresses: {[tokenSymbol: string]: tEthereumAddress}
|
||||
): [string[], string[]] => {
|
||||
const {ETH, USD, WETH, ...assetsAddressesWithoutEth} = allAssetsAddresses;
|
||||
|
||||
const pairs = Object.entries(assetsAddressesWithoutEth).map(([tokenSymbol, tokenAddress]) => {
|
||||
if (tokenSymbol !== 'WETH' && tokenSymbol !== 'ETH') {
|
||||
const aggregatorAddressIndex = Object.keys(aggregatorsAddresses).findIndex(
|
||||
(value) => value === tokenSymbol
|
||||
);
|
||||
const [, aggregatorAddress] = (Object.entries(aggregatorsAddresses) as [
|
||||
string,
|
||||
tEthereumAddress
|
||||
][])[aggregatorAddressIndex];
|
||||
return [tokenAddress, aggregatorAddress];
|
||||
}
|
||||
}) as [string, string][];
|
||||
|
||||
const mappedPairs = pairs.map(([asset]) => asset);
|
||||
const mappedAggregators = pairs.map(([, source]) => source);
|
||||
|
||||
return [mappedPairs, mappedAggregators];
|
||||
};
|
||||
|
||||
export const initReserves = async (
|
||||
reservesParams: iMultiPoolsAssets<IReserveParams>,
|
||||
tokenAddresses: {[symbol: string]: tEthereumAddress},
|
||||
lendingPoolAddressesProvider: LendingPoolAddressesProvider,
|
||||
lendingPool: LendingPool,
|
||||
helpers: AaveProtocolTestHelpers,
|
||||
lendingPoolConfigurator: LendingPoolConfigurator,
|
||||
aavePool: AavePools,
|
||||
incentivesController: tEthereumAddress,
|
||||
verify: boolean
|
||||
) => {
|
||||
if (aavePool !== AavePools.proto && aavePool !== AavePools.secondary) {
|
||||
console.log(`Invalid Aave pool ${aavePool}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
for (let [assetSymbol, {reserveDecimals}] of Object.entries(reservesParams) as [
|
||||
string,
|
||||
IReserveParams
|
||||
][]) {
|
||||
const assetAddressIndex = Object.keys(tokenAddresses).findIndex(
|
||||
(value) => value === assetSymbol
|
||||
);
|
||||
const [, tokenAddress] = (Object.entries(tokenAddresses) as [string, string][])[
|
||||
assetAddressIndex
|
||||
];
|
||||
|
||||
const {isActive: reserveInitialized} = await helpers.getReserveConfigurationData(tokenAddress);
|
||||
|
||||
if (reserveInitialized) {
|
||||
console.log(`Reserve ${assetSymbol} is already active, skipping configuration`);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const reserveParamIndex = Object.keys(reservesParams).findIndex(
|
||||
(value) => value === assetSymbol
|
||||
);
|
||||
const [
|
||||
,
|
||||
{
|
||||
baseVariableBorrowRate,
|
||||
variableRateSlope1,
|
||||
variableRateSlope2,
|
||||
stableRateSlope1,
|
||||
stableRateSlope2,
|
||||
},
|
||||
] = (Object.entries(reservesParams) as [string, IReserveParams][])[reserveParamIndex];
|
||||
console.log('deploy the interest rate strategy for ', assetSymbol);
|
||||
const rateStrategyContract = await deployDefaultReserveInterestRateStrategy(
|
||||
[
|
||||
lendingPoolAddressesProvider.address,
|
||||
baseVariableBorrowRate,
|
||||
variableRateSlope1,
|
||||
variableRateSlope2,
|
||||
stableRateSlope1,
|
||||
stableRateSlope2,
|
||||
],
|
||||
verify
|
||||
);
|
||||
|
||||
console.log('deploy the stable debt totken for ', assetSymbol);
|
||||
const stableDebtToken = await deployStableDebtToken(
|
||||
[
|
||||
`Aave stable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
|
||||
`stableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
|
||||
tokenAddress,
|
||||
lendingPool.address,
|
||||
incentivesController,
|
||||
],
|
||||
verify
|
||||
);
|
||||
|
||||
console.log('deploy the variable debt totken for ', assetSymbol);
|
||||
const variableDebtToken = await deployVariableDebtToken(
|
||||
[
|
||||
`Aave variable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
|
||||
`variableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
|
||||
tokenAddress,
|
||||
lendingPool.address,
|
||||
incentivesController,
|
||||
],
|
||||
verify
|
||||
);
|
||||
|
||||
console.log('deploy the aToken for ', assetSymbol);
|
||||
const aToken = await deployGenericAToken(
|
||||
[
|
||||
lendingPool.address,
|
||||
tokenAddress,
|
||||
`Aave interest bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
|
||||
`a${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
|
||||
incentivesController,
|
||||
],
|
||||
verify
|
||||
);
|
||||
|
||||
if (process.env.POOL === AavePools.secondary) {
|
||||
if (assetSymbol.search('UNI') === -1) {
|
||||
assetSymbol = `Uni${assetSymbol}`;
|
||||
} else {
|
||||
assetSymbol = assetSymbol.replace(/_/g, '').replace('UNI', 'Uni');
|
||||
}
|
||||
}
|
||||
|
||||
console.log('initialize the reserve ', assetSymbol);
|
||||
await lendingPoolConfigurator.initReserve(
|
||||
aToken.address,
|
||||
stableDebtToken.address,
|
||||
variableDebtToken.address,
|
||||
reserveDecimals,
|
||||
rateStrategyContract.address
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(`Reserve initialization for ${assetSymbol} failed with error ${e}. Skipped.`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const getLendingPoolAddressesProviderRegistry = async (address?: tEthereumAddress) => {
|
||||
return await getContract<LendingPoolAddressesProviderRegistry>(
|
||||
eContractid.LendingPoolAddressesProviderRegistry,
|
||||
address ||
|
||||
(
|
||||
await getDb()
|
||||
.get(`${eContractid.LendingPoolAddressesProviderRegistry}.${BRE.network.name}`)
|
||||
.value()
|
||||
).address
|
||||
);
|
||||
};
|
||||
|
||||
export const buildPermitParams = (
|
||||
chainId: number,
|
||||
token: tEthereumAddress,
|
||||
|
|
|
@ -1,57 +1,256 @@
|
|||
import {iMultiPoolsAssets, IReserveParams, tEthereumAddress} from './types';
|
||||
import {LendingPool} from '../types/LendingPool';
|
||||
import {LendingPoolConfigurator} from '../types/LendingPoolConfigurator';
|
||||
import {AaveProtocolTestHelpers} from '../types/AaveProtocolTestHelpers';
|
||||
import {waitForTx} from './misc-utils';
|
||||
import {
|
||||
deployATokensAndRatesHelper,
|
||||
deployStableAndVariableTokensHelper,
|
||||
} from './contracts-deployments';
|
||||
import {chunk, waitForTx} from './misc-utils';
|
||||
import {
|
||||
getATokensAndRatesHelper,
|
||||
getLendingPoolAddressesProvider,
|
||||
getStableAndVariableTokensHelper,
|
||||
} from './contracts-getters';
|
||||
|
||||
export const enableReservesToBorrow = async (
|
||||
export const initReservesByHelper = async (
|
||||
reservesParams: iMultiPoolsAssets<IReserveParams>,
|
||||
tokenAddresses: {[symbol: string]: tEthereumAddress},
|
||||
helpers: AaveProtocolTestHelpers,
|
||||
lendingPoolConfigurator: LendingPoolConfigurator
|
||||
admin: tEthereumAddress,
|
||||
incentivesController: tEthereumAddress
|
||||
) => {
|
||||
for (const [assetSymbol, {borrowingEnabled, stableBorrowRateEnabled}] of Object.entries(
|
||||
reservesParams
|
||||
) as [string, IReserveParams][]) {
|
||||
if (!borrowingEnabled) continue;
|
||||
try {
|
||||
const stableAndVariableDeployer = await getStableAndVariableTokensHelper();
|
||||
const atokenAndRatesDeployer = await getATokensAndRatesHelper();
|
||||
|
||||
const addressProvider = await getLendingPoolAddressesProvider();
|
||||
|
||||
// Set aTokenAndRatesDeployer as temporal admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(atokenAndRatesDeployer.address));
|
||||
|
||||
// CHUNK CONFIGURATION
|
||||
const tokensChunks = 4;
|
||||
const initChunks = 6;
|
||||
|
||||
// Deploy tokens and rates in chunks
|
||||
const reservesChunks = chunk(
|
||||
Object.entries(reservesParams) as [string, IReserveParams][],
|
||||
tokensChunks
|
||||
);
|
||||
// Initialize variables for future reserves initialization
|
||||
let deployedStableTokens: string[] = [];
|
||||
let deployedVariableTokens: string[] = [];
|
||||
let deployedATokens: string[] = [];
|
||||
let deployedRates: string[] = [];
|
||||
let reserveTokens: string[] = [];
|
||||
let reserveInitDecimals: string[] = [];
|
||||
|
||||
console.log(
|
||||
`- Token deployments in ${reservesChunks.length * 2} txs instead of ${
|
||||
Object.entries(reservesParams).length * 4
|
||||
} txs`
|
||||
);
|
||||
for (let reservesChunk of reservesChunks) {
|
||||
// Prepare data
|
||||
const tokens: string[] = [];
|
||||
const symbols: string[] = [];
|
||||
const strategyRates: string[][] = [];
|
||||
const reservesDecimals: string[] = [];
|
||||
|
||||
for (let [assetSymbol, {reserveDecimals}] of reservesChunk) {
|
||||
const assetAddressIndex = Object.keys(tokenAddresses).findIndex(
|
||||
(value) => value === assetSymbol
|
||||
);
|
||||
const [, tokenAddress] = (Object.entries(tokenAddresses) as [string, string][])[
|
||||
assetAddressIndex
|
||||
];
|
||||
const {borrowingEnabled: borrowingAlreadyEnabled} = await helpers.getReserveConfigurationData(
|
||||
tokenAddress
|
||||
);
|
||||
|
||||
if (borrowingAlreadyEnabled) {
|
||||
console.log(`Reserve ${assetSymbol} is already enabled for borrowing, skipping`);
|
||||
continue;
|
||||
}
|
||||
|
||||
console.log('Enabling borrowing on reserve ', assetSymbol);
|
||||
|
||||
await waitForTx(
|
||||
await lendingPoolConfigurator.enableBorrowingOnReserve(
|
||||
tokenAddress,
|
||||
stableBorrowRateEnabled
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(
|
||||
`Enabling reserve for borrowings for ${assetSymbol} failed with error ${e}. Skipped.`
|
||||
const reserveParamIndex = Object.keys(reservesParams).findIndex(
|
||||
(value) => value === assetSymbol
|
||||
);
|
||||
const [
|
||||
,
|
||||
{
|
||||
baseVariableBorrowRate,
|
||||
variableRateSlope1,
|
||||
variableRateSlope2,
|
||||
stableRateSlope1,
|
||||
stableRateSlope2,
|
||||
},
|
||||
] = (Object.entries(reservesParams) as [string, IReserveParams][])[reserveParamIndex];
|
||||
// Add to lists
|
||||
tokens.push(tokenAddress);
|
||||
symbols.push(assetSymbol);
|
||||
strategyRates.push([
|
||||
baseVariableBorrowRate,
|
||||
variableRateSlope1,
|
||||
variableRateSlope2,
|
||||
stableRateSlope1,
|
||||
stableRateSlope2,
|
||||
]);
|
||||
reservesDecimals.push(reserveDecimals);
|
||||
}
|
||||
|
||||
// Deploy stable and variable deployers
|
||||
const tx1 = await waitForTx(
|
||||
await stableAndVariableDeployer.initDeployment(tokens, symbols, incentivesController)
|
||||
);
|
||||
|
||||
// Deploy atokens and rate strategies
|
||||
const tx2 = await waitForTx(
|
||||
await atokenAndRatesDeployer.initDeployment(
|
||||
tokens,
|
||||
symbols,
|
||||
strategyRates,
|
||||
incentivesController
|
||||
)
|
||||
);
|
||||
console.log(` - Deployed aToken, DebtTokens and Strategy for: ${symbols.join(', ')} `);
|
||||
const stableTokens: string[] = tx1.events?.map((e) => e.args?.stableToken) || [];
|
||||
const variableTokens: string[] = tx1.events?.map((e) => e.args?.variableToken) || [];
|
||||
const aTokens: string[] = tx2.events?.map((e) => e.args?.aToken) || [];
|
||||
const strategies: string[] = tx2.events?.map((e) => e.args?.strategy) || [];
|
||||
|
||||
deployedStableTokens = [...deployedStableTokens, ...stableTokens];
|
||||
deployedVariableTokens = [...deployedVariableTokens, ...variableTokens];
|
||||
deployedATokens = [...deployedATokens, ...aTokens];
|
||||
deployedRates = [...deployedRates, ...strategies];
|
||||
reserveInitDecimals = [...reserveInitDecimals, ...reservesDecimals];
|
||||
reserveTokens = [...reserveTokens, ...tokens];
|
||||
}
|
||||
|
||||
// Deploy init reserves per chunks
|
||||
const chunkedStableTokens = chunk(deployedStableTokens, initChunks);
|
||||
const chunkedVariableTokens = chunk(deployedVariableTokens, initChunks);
|
||||
const chunkedAtokens = chunk(deployedATokens, initChunks);
|
||||
const chunkedRates = chunk(deployedRates, initChunks);
|
||||
const chunkedDecimals = chunk(reserveInitDecimals, initChunks);
|
||||
const chunkedSymbols = chunk(Object.keys(tokenAddresses), initChunks);
|
||||
|
||||
console.log(`- Reserves initialization in ${chunkedStableTokens.length} txs`);
|
||||
for (let chunkIndex = 0; chunkIndex < chunkedDecimals.length; chunkIndex++) {
|
||||
const tx3 = await waitForTx(
|
||||
await atokenAndRatesDeployer.initReserve(
|
||||
chunkedStableTokens[chunkIndex],
|
||||
chunkedVariableTokens[chunkIndex],
|
||||
chunkedAtokens[chunkIndex],
|
||||
chunkedRates[chunkIndex],
|
||||
chunkedDecimals[chunkIndex]
|
||||
)
|
||||
);
|
||||
console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`);
|
||||
}
|
||||
|
||||
// Set deployer back as admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(admin));
|
||||
};
|
||||
|
||||
export const enableReservesAsCollateral = async (
|
||||
export const getPairsTokenAggregator = (
|
||||
allAssetsAddresses: {
|
||||
[tokenSymbol: string]: tEthereumAddress;
|
||||
},
|
||||
aggregatorsAddresses: {[tokenSymbol: string]: tEthereumAddress}
|
||||
): [string[], string[]] => {
|
||||
const {ETH, USD, WETH, ...assetsAddressesWithoutEth} = allAssetsAddresses;
|
||||
|
||||
const pairs = Object.entries(assetsAddressesWithoutEth).map(([tokenSymbol, tokenAddress]) => {
|
||||
if (tokenSymbol !== 'WETH' && tokenSymbol !== 'ETH') {
|
||||
const aggregatorAddressIndex = Object.keys(aggregatorsAddresses).findIndex(
|
||||
(value) => value === tokenSymbol
|
||||
);
|
||||
const [, aggregatorAddress] = (Object.entries(aggregatorsAddresses) as [
|
||||
string,
|
||||
tEthereumAddress
|
||||
][])[aggregatorAddressIndex];
|
||||
return [tokenAddress, aggregatorAddress];
|
||||
}
|
||||
}) as [string, string][];
|
||||
|
||||
const mappedPairs = pairs.map(([asset]) => asset);
|
||||
const mappedAggregators = pairs.map(([, source]) => source);
|
||||
|
||||
return [mappedPairs, mappedAggregators];
|
||||
};
|
||||
|
||||
export const enableReservesToBorrowByHelper = async (
|
||||
reservesParams: iMultiPoolsAssets<IReserveParams>,
|
||||
tokenAddresses: {[symbol: string]: tEthereumAddress},
|
||||
helpers: AaveProtocolTestHelpers,
|
||||
lendingPoolConfigurator: LendingPoolConfigurator
|
||||
admin: tEthereumAddress
|
||||
) => {
|
||||
const addressProvider = await getLendingPoolAddressesProvider();
|
||||
const atokenAndRatesDeployer = await getATokensAndRatesHelper();
|
||||
const tokens: string[] = [];
|
||||
const symbols: string[] = [];
|
||||
const stableEnabled: boolean[] = [];
|
||||
|
||||
// Prepare data
|
||||
for (const [assetSymbol, {borrowingEnabled, stableBorrowRateEnabled}] of Object.entries(
|
||||
reservesParams
|
||||
) as [string, IReserveParams][]) {
|
||||
if (!borrowingEnabled) continue;
|
||||
const assetAddressIndex = Object.keys(tokenAddresses).findIndex(
|
||||
(value) => value === assetSymbol
|
||||
);
|
||||
const [, tokenAddress] = (Object.entries(tokenAddresses) as [string, string][])[
|
||||
assetAddressIndex
|
||||
];
|
||||
const {borrowingEnabled: borrowingAlreadyEnabled} = await helpers.getReserveConfigurationData(
|
||||
tokenAddress
|
||||
);
|
||||
|
||||
if (borrowingAlreadyEnabled) {
|
||||
console.log(`Reserve ${assetSymbol} is already enabled for borrowing, skipping`);
|
||||
continue;
|
||||
}
|
||||
tokens.push(tokenAddress);
|
||||
stableEnabled.push(stableBorrowRateEnabled);
|
||||
symbols.push(assetSymbol);
|
||||
}
|
||||
if (tokens.length) {
|
||||
// Set aTokenAndRatesDeployer as temporal admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(atokenAndRatesDeployer.address));
|
||||
|
||||
// Deploy init per chunks
|
||||
const stableChunks = 20;
|
||||
const chunkedTokens = chunk(tokens, stableChunks);
|
||||
const chunkedSymbols = chunk(symbols, stableChunks);
|
||||
const chunkedStableEnabled = chunk(stableEnabled, stableChunks);
|
||||
|
||||
console.log(`- Borrow stable initialization in ${chunkedTokens.length} txs`);
|
||||
for (let chunkIndex = 0; chunkIndex < chunkedTokens.length; chunkIndex++) {
|
||||
try {
|
||||
await waitForTx(
|
||||
await atokenAndRatesDeployer.enableBorrowingOnReserves(
|
||||
chunkedTokens[chunkIndex],
|
||||
chunkedStableEnabled[chunkIndex],
|
||||
{gasLimit: 12000000}
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
console.log(` - Init for: ${chunkedSymbols[chunkIndex].join(', ')}`);
|
||||
}
|
||||
// Set deployer back as admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(admin));
|
||||
}
|
||||
};
|
||||
|
||||
export const enableReservesAsCollateralByHelper = async (
|
||||
reservesParams: iMultiPoolsAssets<IReserveParams>,
|
||||
tokenAddresses: {[symbol: string]: tEthereumAddress},
|
||||
helpers: AaveProtocolTestHelpers,
|
||||
admin: tEthereumAddress
|
||||
) => {
|
||||
const addressProvider = await getLendingPoolAddressesProvider();
|
||||
const atokenAndRatesDeployer = await getATokensAndRatesHelper();
|
||||
const tokens: string[] = [];
|
||||
const symbols: string[] = [];
|
||||
const baseLTVA: string[] = [];
|
||||
const liquidationThresholds: string[] = [];
|
||||
const liquidationBonuses: string[] = [];
|
||||
|
||||
for (const [
|
||||
assetSymbol,
|
||||
{baseLTVAsCollateral, liquidationBonus, liquidationThreshold},
|
||||
|
@ -69,25 +268,42 @@ export const enableReservesAsCollateral = async (
|
|||
);
|
||||
|
||||
if (alreadyEnabled) {
|
||||
console.log(`Reserve ${assetSymbol} is already enabled as collateral, skipping`);
|
||||
console.log(`- Reserve ${assetSymbol} is already enabled as collateral, skipping`);
|
||||
continue;
|
||||
}
|
||||
// Push data
|
||||
tokens.push(tokenAddress);
|
||||
symbols.push(assetSymbol);
|
||||
baseLTVA.push(baseLTVAsCollateral);
|
||||
liquidationThresholds.push(liquidationThreshold);
|
||||
liquidationBonuses.push(liquidationBonus);
|
||||
}
|
||||
if (tokens.length) {
|
||||
// Set aTokenAndRatesDeployer as temporal admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(atokenAndRatesDeployer.address));
|
||||
|
||||
try {
|
||||
console.log(`Enabling reserve ${assetSymbol} as collateral`);
|
||||
// Deploy init per chunks
|
||||
const enableChunks = 20;
|
||||
const chunkedTokens = chunk(tokens, enableChunks);
|
||||
const chunkedSymbols = chunk(symbols, enableChunks);
|
||||
const chunkedBase = chunk(baseLTVA, enableChunks);
|
||||
const chunkedliquidationThresholds = chunk(liquidationThresholds, enableChunks);
|
||||
const chunkedliquidationBonuses = chunk(liquidationBonuses, enableChunks);
|
||||
|
||||
console.log(`- Enable reserve as collateral in ${chunkedTokens.length} txs`);
|
||||
for (let chunkIndex = 0; chunkIndex < chunkedTokens.length; chunkIndex++) {
|
||||
await waitForTx(
|
||||
await lendingPoolConfigurator.enableReserveAsCollateral(
|
||||
tokenAddress,
|
||||
baseLTVAsCollateral,
|
||||
liquidationThreshold,
|
||||
liquidationBonus
|
||||
await atokenAndRatesDeployer.enableReservesAsCollateral(
|
||||
chunkedTokens[chunkIndex],
|
||||
chunkedBase[chunkIndex],
|
||||
chunkedliquidationThresholds[chunkIndex],
|
||||
chunkedliquidationBonuses[chunkIndex],
|
||||
{gasLimit: 12000000}
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(
|
||||
`Enabling reserve as collateral for ${assetSymbol} failed with error ${e}. Skipped.`
|
||||
);
|
||||
console.log(` - Init for: ${chunkedSymbols[chunkIndex].join(', ')}`);
|
||||
}
|
||||
// Set deployer back as admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(admin));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,6 +5,8 @@ import FileSync from 'lowdb/adapters/FileSync';
|
|||
import {WAD} from './constants';
|
||||
import {Wallet, ContractTransaction} from 'ethers';
|
||||
import {BuidlerRuntimeEnvironment} from '@nomiclabs/buidler/types';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
export const toWad = (value: string | number) => new BigNumber(value).times(WAD).toFixed();
|
||||
|
||||
|
@ -50,3 +52,13 @@ export const filterMapBy = (raw: {[key: string]: any}, fn: (key: string) => bool
|
|||
obj[key] = raw[key];
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
export const chunk = <T>(arr: Array<T>, chunkSize: number): Array<Array<T>> => {
|
||||
return arr.reduce(
|
||||
(prevVal: any, currVal: any, currIndx: number, array: Array<T>) =>
|
||||
!(currIndx % chunkSize)
|
||||
? prevVal.concat([array.slice(currIndx, currIndx + chunkSize)])
|
||||
: prevVal,
|
||||
[]
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,22 +4,26 @@ import {
|
|||
IMarketRates,
|
||||
iAssetBase,
|
||||
iAssetAggregatorBase,
|
||||
eContractid,
|
||||
SymbolMap,
|
||||
} from './types';
|
||||
|
||||
import {LendingRateOracle} from '../types/LendingRateOracle';
|
||||
import {PriceOracle} from '../types/PriceOracle';
|
||||
import {MockAggregator} from '../types/MockAggregator';
|
||||
import {deployMockAggregator, getContract, MockTokenMap} from './contracts-helpers';
|
||||
import {waitForTx} from './misc-utils';
|
||||
import {verifyContract} from './etherscan-verification';
|
||||
import {deployMockAggregator} from './contracts-deployments';
|
||||
import {chunk, waitForTx} from './misc-utils';
|
||||
import {getStableAndVariableTokensHelper} from './contracts-getters';
|
||||
|
||||
export const setInitialMarketRatesInRatesOracle = async (
|
||||
export const setInitialMarketRatesInRatesOracleByHelper = async (
|
||||
marketRates: iMultiPoolsAssets<IMarketRates>,
|
||||
assetsAddresses: {[x: string]: tEthereumAddress},
|
||||
lendingRateOracleInstance: LendingRateOracle
|
||||
lendingRateOracleInstance: LendingRateOracle,
|
||||
admin: tEthereumAddress
|
||||
) => {
|
||||
const stableAndVariableTokenHelper = await getStableAndVariableTokensHelper();
|
||||
const assetAddresses: string[] = [];
|
||||
const borrowRates: string[] = [];
|
||||
const symbols: string[] = [];
|
||||
for (const [assetSymbol, {borrowRate}] of Object.entries(marketRates) as [
|
||||
string,
|
||||
IMarketRates
|
||||
|
@ -30,9 +34,36 @@ export const setInitialMarketRatesInRatesOracle = async (
|
|||
const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[
|
||||
assetAddressIndex
|
||||
];
|
||||
await waitForTx(await lendingRateOracleInstance.setMarketBorrowRate(assetAddress, borrowRate));
|
||||
console.log('added Market Borrow Rate for: ', assetSymbol);
|
||||
assetAddresses.push(assetAddress);
|
||||
borrowRates.push(borrowRate);
|
||||
symbols.push(assetSymbol);
|
||||
}
|
||||
// Set borrow rates per chunks
|
||||
const ratesChunks = 20;
|
||||
const chunkedTokens = chunk(assetAddresses, ratesChunks);
|
||||
const chunkedRates = chunk(borrowRates, ratesChunks);
|
||||
const chunkedSymbols = chunk(symbols, ratesChunks);
|
||||
|
||||
// Set helper as owner
|
||||
await waitForTx(
|
||||
await lendingRateOracleInstance.transferOwnership(stableAndVariableTokenHelper.address)
|
||||
);
|
||||
|
||||
console.log(`- Oracle borrow initalization in ${chunkedTokens.length} txs`);
|
||||
for (let chunkIndex = 0; chunkIndex < chunkedTokens.length; chunkIndex++) {
|
||||
const tx3 = await waitForTx(
|
||||
await stableAndVariableTokenHelper.setOracleBorrowRates(
|
||||
chunkedTokens[chunkIndex],
|
||||
chunkedRates[chunkIndex],
|
||||
lendingRateOracleInstance.address
|
||||
)
|
||||
);
|
||||
console.log(` - Setted Oracle Borrow Rates for: ${chunkedSymbols[chunkIndex].join(', ')}`);
|
||||
}
|
||||
// Set back ownership
|
||||
await waitForTx(
|
||||
await stableAndVariableTokenHelper.setOracleOwnership(lendingRateOracleInstance.address, admin)
|
||||
);
|
||||
};
|
||||
|
||||
export const setInitialAssetPricesInOracle = async (
|
||||
|
|
|
@ -56,6 +56,8 @@ export enum eContractid {
|
|||
VariableDebtToken = 'VariableDebtToken',
|
||||
FeeProvider = 'FeeProvider',
|
||||
TokenDistributor = 'TokenDistributor',
|
||||
StableAndVariableTokensHelper = 'StableAndVariableTokensHelper',
|
||||
ATokensAndRatesHelper = 'ATokensAndRatesHelper',
|
||||
UiPoolDataProvider = 'UiPoolDataProvider',
|
||||
}
|
||||
|
||||
|
@ -91,6 +93,7 @@ export enum ProtocolErrors {
|
|||
REQUESTED_AMOUNT_TOO_SMALL = '25', // 'The requested amount is too small for a FlashLoan.'
|
||||
INCONSISTENT_PROTOCOL_ACTUAL_BALANCE = '26', // 'The actual balance of the protocol is inconsistent'
|
||||
CALLER_NOT_LENDING_POOL_CONFIGURATOR = '27', // 'The actual balance of the protocol is inconsistent'
|
||||
BORROW_ALLOWANCE_ARE_NOT_ENOUGH = '54', // User borrows on behalf, but allowance are too small
|
||||
INVALID_FLASH_LOAN_EXECUTOR_RETURN = '60', // The flash loan received returned 0 (EOA)
|
||||
|
||||
// require error messages - aToken
|
||||
|
@ -119,6 +122,12 @@ export enum ProtocolErrors {
|
|||
|
||||
IS_PAUSED = '58', // Pool is paused
|
||||
|
||||
INVALID_LTV = '70',
|
||||
INVALID_LIQ_THRESHOLD = '71',
|
||||
INVALID_LIQ_BONUS = '72',
|
||||
INVALID_DECIMALS = '73',
|
||||
INVALID_RESERVE_FACTOR = '74',
|
||||
|
||||
// old
|
||||
|
||||
INVALID_FROM_BALANCE_AFTER_TRANSFER = 'Invalid from balance after transfer',
|
||||
|
|
7327
package-lock.json
generated
7327
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -11,7 +11,7 @@
|
|||
"buidler:docker": "buidler --network buidlerevm_docker",
|
||||
"buidler help": "buidler help",
|
||||
"compile": "SKIP_LOAD=true buidler compile",
|
||||
"types-gen": "typechain --target ethers-v5 --outDir ./types './artifacts/*.json'",
|
||||
"types-gen": "npm run compile -- --force && typechain --target ethers-v5 --outDir ./types './artifacts/*.json'",
|
||||
"test": "buidler test",
|
||||
"test-scenarios": "buidler test test/__setup.spec.ts test/scenario.spec.ts",
|
||||
"aave:evm:dev:migration": "buidler aave:dev",
|
||||
|
@ -37,8 +37,10 @@
|
|||
"test-transfers": "buidler test test/__setup.spec.ts test/atoken-transfer.spec.ts",
|
||||
"test-flash": "buidler test test/__setup.spec.ts test/flashloan.spec.ts",
|
||||
"test-liquidate": "buidler test test/__setup.spec.ts test/liquidation-atoken.spec.ts",
|
||||
"test-deploy": "buidler test test/__setup.spec.ts test/test-init.spec.ts",
|
||||
"test-pausable": "buidler test test/__setup.spec.ts test/pausable-functions.spec.ts",
|
||||
"test-permit": "buidler test test/__setup.spec.ts test/atoken-permit.spec.ts",
|
||||
"test-stable-and-atokens": "buidler test test/__setup.spec.ts test/atoken-transfer.spec.ts test/stable-token.spec.ts",
|
||||
"test-subgraph:scenarios": "buidler --network buidlerevm_docker test test/__setup.spec.ts test/subgraph-scenarios.spec.ts",
|
||||
"dev:coverage": "buidler coverage --network coverage",
|
||||
"dev:deployment": "buidler dev-deployment",
|
||||
|
|
27
tasks/deployments/deploy-UiPoolDataProvider.ts
Normal file
27
tasks/deployments/deploy-UiPoolDataProvider.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
|
||||
import {UiPoolDataProviderFactory} from '../../types';
|
||||
import {verifyContract} from '../../helpers/etherscan-verification';
|
||||
import {eContractid} from '../../helpers/types';
|
||||
|
||||
task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider contract`)
|
||||
.addFlag('verify', 'Verify UiPoolDataProvider contract via Etherscan API.')
|
||||
.setAction(async ({verify}, localBRE) => {
|
||||
await localBRE.run('set-bre');
|
||||
|
||||
if (!localBRE.network.config.chainId) {
|
||||
throw new Error('INVALID_CHAIN_ID');
|
||||
}
|
||||
|
||||
console.log(`\n- UiPoolDataProvider deployment`);
|
||||
|
||||
console.log(`\tDeploying UiPoolDataProvider implementation ...`);
|
||||
const uiPoolDataProvider = await new UiPoolDataProviderFactory(
|
||||
await localBRE.ethers.provider.getSigner()
|
||||
).deploy();
|
||||
await uiPoolDataProvider.deployTransaction.wait();
|
||||
console.log('uiPoolDataProvider.address', uiPoolDataProvider.address);
|
||||
await verifyContract(eContractid.UiPoolDataProvider, uiPoolDataProvider.address, []);
|
||||
|
||||
console.log(`\tFinished UiPoolDataProvider proxy and implementation deployment`);
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {deployAllMockTokens} from '../../helpers/contracts-helpers';
|
||||
import {deployAllMockTokens} from '../../helpers/contracts-deployments';
|
||||
task('dev:deploy-mock-tokens', 'Deploy mock tokens for dev enviroment')
|
||||
.addOptionalParam('verify', 'Verify contracts at Etherscan')
|
||||
.setAction(async ({verify}, localBRE) => {
|
||||
|
|
|
@ -2,7 +2,7 @@ import {task} from '@nomiclabs/buidler/config';
|
|||
import {
|
||||
deployLendingPoolAddressesProvider,
|
||||
deployLendingPoolAddressesProviderRegistry,
|
||||
} from '../../helpers/contracts-helpers';
|
||||
} from '../../helpers/contracts-deployments';
|
||||
import {waitForTx} from '../../helpers/misc-utils';
|
||||
|
||||
task(
|
||||
|
@ -20,6 +20,6 @@ task(
|
|||
|
||||
const addressesProviderRegistry = await deployLendingPoolAddressesProviderRegistry(verify);
|
||||
await waitForTx(
|
||||
await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 0)
|
||||
await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 1)
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {
|
||||
deployATokensAndRatesHelper,
|
||||
deployLendingPool,
|
||||
getLendingPoolAddressesProvider,
|
||||
getLendingPool,
|
||||
insertContractAddressInDb,
|
||||
deployLendingPoolConfigurator,
|
||||
getLendingPoolConfiguratorProxy,
|
||||
} from '../../helpers/contracts-helpers';
|
||||
deployStableAndVariableTokensHelper,
|
||||
} from '../../helpers/contracts-deployments';
|
||||
import {eContractid} from '../../helpers/types';
|
||||
import {waitForTx} from '../../helpers/misc-utils';
|
||||
import {
|
||||
getLendingPoolAddressesProvider,
|
||||
getLendingPool,
|
||||
getLendingPoolConfiguratorProxy,
|
||||
} from '../../helpers/contracts-getters';
|
||||
import {insertContractAddressInDb} from '../../helpers/contracts-helpers';
|
||||
|
||||
task('dev:deploy-lending-pool', 'Deploy lending pool for dev enviroment')
|
||||
.addOptionalParam('verify', 'Verify contracts at Etherscan')
|
||||
|
@ -41,4 +45,14 @@ task('dev:deploy-lending-pool', 'Deploy lending pool for dev enviroment')
|
|||
eContractid.LendingPoolConfigurator,
|
||||
lendingPoolConfiguratorProxy.address
|
||||
);
|
||||
|
||||
// Deploy deployment helpers
|
||||
await deployStableAndVariableTokensHelper(
|
||||
[lendingPoolProxy.address, addressesProvider.address],
|
||||
verify
|
||||
);
|
||||
await deployATokensAndRatesHelper(
|
||||
[lendingPoolProxy.address, addressesProvider.address, lendingPoolConfiguratorProxy.address],
|
||||
verify
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {
|
||||
getLendingPoolAddressesProvider,
|
||||
deployPriceOracle,
|
||||
getMockedTokens,
|
||||
getPairsTokenAggregator,
|
||||
deployChainlinkProxyPriceProvider,
|
||||
deployLendingRateOracle,
|
||||
getAllMockedTokens,
|
||||
} from '../../helpers/contracts-helpers';
|
||||
} from '../../helpers/contracts-deployments';
|
||||
|
||||
import {
|
||||
setInitialAssetPricesInOracle,
|
||||
setInitialMarketRatesInRatesOracle,
|
||||
deployAllMockAggregators,
|
||||
setInitialMarketRatesInRatesOracleByHelper,
|
||||
} from '../../helpers/oracles-helpers';
|
||||
import {ICommonConfiguration, iAssetBase, TokenContractId} from '../../helpers/types';
|
||||
import {waitForTx} from '../../helpers/misc-utils';
|
||||
import {getAllAggregatorsAddresses, getAllTokenAddresses} from '../../helpers/mock-helpers';
|
||||
import {ConfigNames, loadPoolConfig} from '../../helpers/configuration';
|
||||
import {
|
||||
getAllMockedTokens,
|
||||
getLendingPoolAddressesProvider,
|
||||
getPairsTokenAggregator,
|
||||
} from '../../helpers/contracts-getters';
|
||||
|
||||
task('dev:deploy-oracles', 'Deploy oracles for dev enviroment')
|
||||
.addOptionalParam('verify', 'Verify contracts at Etherscan')
|
||||
|
@ -41,6 +42,7 @@ task('dev:deploy-oracles', 'Deploy oracles for dev enviroment')
|
|||
return prev;
|
||||
}, defaultTokenList);
|
||||
const addressesProvider = await getLendingPoolAddressesProvider();
|
||||
const admin = await addressesProvider.getAaveAdmin();
|
||||
|
||||
const fallbackOracle = await deployPriceOracle(verify);
|
||||
await waitForTx(await fallbackOracle.setEthUsdPrice(MockUsdPriceInWei));
|
||||
|
@ -66,9 +68,10 @@ task('dev:deploy-oracles', 'Deploy oracles for dev enviroment')
|
|||
const allReservesAddresses = {
|
||||
...tokensAddressesWithoutUsd,
|
||||
};
|
||||
await setInitialMarketRatesInRatesOracle(
|
||||
await setInitialMarketRatesInRatesOracleByHelper(
|
||||
LendingRateOracleRatesCommon,
|
||||
allReservesAddresses,
|
||||
lendingRateOracle
|
||||
lendingRateOracle,
|
||||
admin
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,23 +1,28 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {
|
||||
getLendingPoolAddressesProvider,
|
||||
initReserves,
|
||||
deployLendingPoolCollateralManager,
|
||||
insertContractAddressInDb,
|
||||
deployMockFlashLoanReceiver,
|
||||
deployWalletBalancerProvider,
|
||||
deployAaveProtocolTestHelpers,
|
||||
getLendingPool,
|
||||
getLendingPoolConfiguratorProxy,
|
||||
getAllMockedTokens,
|
||||
} from '../../helpers/contracts-helpers';
|
||||
} from '../../helpers/contracts-deployments';
|
||||
import {getReservesConfigByPool} from '../../helpers/configuration';
|
||||
|
||||
import {tEthereumAddress, AavePools, eContractid} from '../../helpers/types';
|
||||
import {waitForTx, filterMapBy} from '../../helpers/misc-utils';
|
||||
import {enableReservesToBorrow, enableReservesAsCollateral} from '../../helpers/init-helpers';
|
||||
import {
|
||||
enableReservesToBorrowByHelper,
|
||||
enableReservesAsCollateralByHelper,
|
||||
initReservesByHelper,
|
||||
} from '../../helpers/init-helpers';
|
||||
import {getAllTokenAddresses} from '../../helpers/mock-helpers';
|
||||
import {ZERO_ADDRESS} from '../../helpers/constants';
|
||||
import {
|
||||
getAllMockedTokens,
|
||||
getLendingPool,
|
||||
getLendingPoolConfiguratorProxy,
|
||||
getLendingPoolAddressesProvider,
|
||||
} from '../../helpers/contracts-getters';
|
||||
import {insertContractAddressInDb} from '../../helpers/contracts-helpers';
|
||||
|
||||
task('dev:initialize-lending-pool', 'Initialize lending pool configuration.')
|
||||
.addOptionalParam('verify', 'Verify contracts at Etherscan')
|
||||
|
@ -39,28 +44,20 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.')
|
|||
|
||||
const reservesParams = getReservesConfigByPool(AavePools.proto);
|
||||
|
||||
await initReserves(
|
||||
const admin = await addressesProvider.getAaveAdmin();
|
||||
|
||||
await initReservesByHelper(reservesParams, protoPoolReservesAddresses, admin, ZERO_ADDRESS);
|
||||
await enableReservesToBorrowByHelper(
|
||||
reservesParams,
|
||||
protoPoolReservesAddresses,
|
||||
addressesProvider,
|
||||
lendingPoolProxy,
|
||||
testHelpers,
|
||||
lendingPoolConfiguratorProxy,
|
||||
AavePools.proto,
|
||||
ZERO_ADDRESS,
|
||||
verify
|
||||
admin
|
||||
);
|
||||
await enableReservesToBorrow(
|
||||
await enableReservesAsCollateralByHelper(
|
||||
reservesParams,
|
||||
protoPoolReservesAddresses,
|
||||
testHelpers,
|
||||
lendingPoolConfiguratorProxy
|
||||
);
|
||||
await enableReservesAsCollateral(
|
||||
reservesParams,
|
||||
protoPoolReservesAddresses,
|
||||
testHelpers,
|
||||
lendingPoolConfiguratorProxy
|
||||
admin
|
||||
);
|
||||
|
||||
const collateralManager = await deployLendingPoolCollateralManager(verify);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {getParamPerNetwork} from '../../helpers/contracts-helpers';
|
||||
import {
|
||||
deployLendingPoolAddressesProvider,
|
||||
deployLendingPoolAddressesProviderRegistry,
|
||||
getParamPerNetwork,
|
||||
getLendingPoolAddressesProviderRegistry,
|
||||
} from '../../helpers/contracts-helpers';
|
||||
} from '../../helpers/contracts-deployments';
|
||||
import {waitForTx} from '../../helpers/misc-utils';
|
||||
import {ConfigNames, loadPoolConfig, getGenesisAaveAdmin} from '../../helpers/configuration';
|
||||
import {eEthereumNetwork} from '../../helpers/types';
|
||||
import {getLendingPoolAddressesProviderRegistry} from '../../helpers/contracts-getters';
|
||||
|
||||
task(
|
||||
'full:deploy-address-provider',
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {insertContractAddressInDb} from '../../helpers/contracts-helpers';
|
||||
import {
|
||||
deployATokensAndRatesHelper,
|
||||
deployLendingPool,
|
||||
getLendingPoolAddressesProvider,
|
||||
getLendingPool,
|
||||
insertContractAddressInDb,
|
||||
deployLendingPoolConfigurator,
|
||||
getLendingPoolConfiguratorProxy,
|
||||
} from '../../helpers/contracts-helpers';
|
||||
deployStableAndVariableTokensHelper,
|
||||
} from '../../helpers/contracts-deployments';
|
||||
import {eContractid} from '../../helpers/types';
|
||||
import {waitForTx} from '../../helpers/misc-utils';
|
||||
import {
|
||||
getLendingPoolAddressesProvider,
|
||||
getLendingPool,
|
||||
getLendingPoolConfiguratorProxy,
|
||||
} from '../../helpers/contracts-getters';
|
||||
|
||||
task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment')
|
||||
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||
|
@ -44,4 +48,13 @@ task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment')
|
|||
eContractid.LendingPoolConfigurator,
|
||||
lendingPoolConfiguratorProxy.address
|
||||
);
|
||||
// Deploy deployment helpers
|
||||
await deployStableAndVariableTokensHelper(
|
||||
[lendingPoolProxy.address, addressesProvider.address],
|
||||
verify
|
||||
);
|
||||
await deployATokensAndRatesHelper(
|
||||
[lendingPoolProxy.address, addressesProvider.address, lendingPoolConfiguratorProxy.address],
|
||||
verify
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {getParamPerNetwork} from '../../helpers/contracts-helpers';
|
||||
import {
|
||||
getLendingPoolAddressesProvider,
|
||||
getPairsTokenAggregator,
|
||||
deployChainlinkProxyPriceProvider,
|
||||
deployLendingRateOracle,
|
||||
getParamPerNetwork,
|
||||
} from '../../helpers/contracts-helpers';
|
||||
|
||||
import {setInitialMarketRatesInRatesOracle} from '../../helpers/oracles-helpers';
|
||||
} from '../../helpers/contracts-deployments';
|
||||
import {setInitialMarketRatesInRatesOracleByHelper} from '../../helpers/oracles-helpers';
|
||||
import {ICommonConfiguration, eEthereumNetwork, SymbolMap} from '../../helpers/types';
|
||||
import {waitForTx, filterMapBy} from '../../helpers/misc-utils';
|
||||
import {ConfigNames, loadPoolConfig} from '../../helpers/configuration';
|
||||
import {exit} from 'process';
|
||||
import {
|
||||
getLendingPoolAddressesProvider,
|
||||
getPairsTokenAggregator,
|
||||
} from '../../helpers/contracts-getters';
|
||||
|
||||
task('full:deploy-oracles', 'Deploy oracles for dev enviroment')
|
||||
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||
|
@ -29,11 +30,11 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment')
|
|||
FallbackOracle,
|
||||
ChainlinkAggregator,
|
||||
} = poolConfig as ICommonConfiguration;
|
||||
|
||||
const lendingRateOracles = filterMapBy(LendingRateOracleRatesCommon, (key) =>
|
||||
ReserveSymbols.includes(key)
|
||||
);
|
||||
const addressesProvider = await getLendingPoolAddressesProvider();
|
||||
const admin = await addressesProvider.getAaveAdmin();
|
||||
|
||||
const fallbackOracle = await getParamPerNetwork(FallbackOracle, network);
|
||||
const reserveAssets = await getParamPerNetwork(ReserveAssets, network);
|
||||
|
@ -57,10 +58,11 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment')
|
|||
await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address));
|
||||
|
||||
const {USD, ...tokensAddressesWithoutUsd} = tokensToWatch;
|
||||
await setInitialMarketRatesInRatesOracle(
|
||||
await setInitialMarketRatesInRatesOracleByHelper(
|
||||
lendingRateOracles,
|
||||
tokensAddressesWithoutUsd,
|
||||
lendingRateOracle
|
||||
lendingRateOracle,
|
||||
admin
|
||||
);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
|
|
@ -1,22 +1,25 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {getParamPerNetwork} from '../../helpers/contracts-helpers';
|
||||
import {
|
||||
getLendingPoolAddressesProvider,
|
||||
initReserves,
|
||||
deployLendingPoolCollateralManager,
|
||||
insertContractAddressInDb,
|
||||
deployWalletBalancerProvider,
|
||||
deployAaveProtocolTestHelpers,
|
||||
} from '../../helpers/contracts-deployments';
|
||||
import {loadPoolConfig, ConfigNames} from '../../helpers/configuration';
|
||||
import {eEthereumNetwork, ICommonConfiguration} from '../../helpers/types';
|
||||
import {waitForTx} from '../../helpers/misc-utils';
|
||||
import {
|
||||
initReservesByHelper,
|
||||
enableReservesToBorrowByHelper,
|
||||
enableReservesAsCollateralByHelper,
|
||||
} from '../../helpers/init-helpers';
|
||||
import {exit} from 'process';
|
||||
import {
|
||||
getLendingPool,
|
||||
getLendingPoolConfiguratorProxy,
|
||||
getParamPerNetwork,
|
||||
} from '../../helpers/contracts-helpers';
|
||||
import {loadPoolConfig, ConfigNames} from '../../helpers/configuration';
|
||||
|
||||
import {AavePools, eContractid, eEthereumNetwork, ICommonConfiguration} from '../../helpers/types';
|
||||
import {waitForTx} from '../../helpers/misc-utils';
|
||||
import {enableReservesToBorrow, enableReservesAsCollateral} from '../../helpers/init-helpers';
|
||||
getLendingPoolAddressesProvider,
|
||||
} from '../../helpers/contracts-getters';
|
||||
import {ZERO_ADDRESS} from '../../helpers/constants';
|
||||
import {exit} from 'process';
|
||||
|
||||
task('full:initialize-lending-pool', 'Initialize lending pool configuration.')
|
||||
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||
|
@ -24,7 +27,6 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.')
|
|||
.setAction(async ({verify, pool}, localBRE) => {
|
||||
try {
|
||||
await localBRE.run('set-bre');
|
||||
console.log('init');
|
||||
const network = <eEthereumNetwork>localBRE.network.name;
|
||||
const poolConfig = loadPoolConfig(pool);
|
||||
const {ReserveAssets, ReservesConfig} = poolConfig as ICommonConfiguration;
|
||||
|
@ -37,40 +39,20 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.')
|
|||
|
||||
const testHelpers = await deployAaveProtocolTestHelpers(addressesProvider.address, verify);
|
||||
|
||||
console.log('init reserves');
|
||||
await initReserves(
|
||||
ReservesConfig,
|
||||
reserveAssets,
|
||||
addressesProvider,
|
||||
lendingPoolProxy,
|
||||
testHelpers,
|
||||
lendingPoolConfiguratorProxy,
|
||||
AavePools.proto,
|
||||
ZERO_ADDRESS,
|
||||
verify
|
||||
);
|
||||
console.log('enable reserves');
|
||||
await enableReservesToBorrow(
|
||||
ReservesConfig,
|
||||
reserveAssets,
|
||||
testHelpers,
|
||||
lendingPoolConfiguratorProxy
|
||||
);
|
||||
console.log('enable reserves as collateral');
|
||||
await enableReservesAsCollateral(
|
||||
ReservesConfig,
|
||||
reserveAssets,
|
||||
testHelpers,
|
||||
lendingPoolConfiguratorProxy
|
||||
);
|
||||
const admin = await addressesProvider.getAaveAdmin();
|
||||
if (!reserveAssets) {
|
||||
throw 'Reserve assets is undefined. Check ReserveAssets configuration at config directory';
|
||||
}
|
||||
|
||||
await initReservesByHelper(ReservesConfig, reserveAssets, admin, ZERO_ADDRESS);
|
||||
await enableReservesToBorrowByHelper(ReservesConfig, reserveAssets, testHelpers, admin);
|
||||
await enableReservesAsCollateralByHelper(ReservesConfig, reserveAssets, testHelpers, admin);
|
||||
|
||||
console.log('deploy coll manager');
|
||||
const collateralManager = await deployLendingPoolCollateralManager(verify);
|
||||
await waitForTx(
|
||||
await addressesProvider.setLendingPoolCollateralManager(collateralManager.address)
|
||||
);
|
||||
|
||||
console.log('deploy bal provicer');
|
||||
await deployWalletBalancerProvider(addressesProvider.address, verify);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import rawBRE from '@nomiclabs/buidler';
|
||||
import {MockContract} from 'ethereum-waffle';
|
||||
import {
|
||||
insertContractAddressInDb,
|
||||
getEthersSigners,
|
||||
registerContractInJsonDb,
|
||||
} from '../helpers/contracts-helpers';
|
||||
import {
|
||||
deployLendingPoolAddressesProvider,
|
||||
deployMintableERC20,
|
||||
|
@ -7,36 +12,39 @@ import {
|
|||
deployLendingPoolConfigurator,
|
||||
deployLendingPool,
|
||||
deployPriceOracle,
|
||||
getLendingPoolConfiguratorProxy,
|
||||
deployChainlinkProxyPriceProvider,
|
||||
deployLendingPoolCollateralManager,
|
||||
deployMockFlashLoanReceiver,
|
||||
deployWalletBalancerProvider,
|
||||
getLendingPool,
|
||||
insertContractAddressInDb,
|
||||
deployAaveProtocolTestHelpers,
|
||||
getEthersSigners,
|
||||
registerContractInJsonDb,
|
||||
getPairsTokenAggregator,
|
||||
initReserves,
|
||||
deployLendingRateOracle,
|
||||
} from '../helpers/contracts-helpers';
|
||||
deployStableAndVariableTokensHelper,
|
||||
deployATokensAndRatesHelper,
|
||||
} from '../helpers/contracts-deployments';
|
||||
import {Signer} from 'ethers';
|
||||
import {TokenContractId, eContractid, tEthereumAddress, AavePools} from '../helpers/types';
|
||||
import {MintableErc20 as MintableERC20} from '../types/MintableErc20';
|
||||
import {getReservesConfigByPool} from '../helpers/configuration';
|
||||
import {initializeMakeSuite} from './helpers/make-suite';
|
||||
import {AaveProtocolTestHelpers} from '../types/AaveProtocolTestHelpers';
|
||||
|
||||
import {
|
||||
setInitialAssetPricesInOracle,
|
||||
setInitialMarketRatesInRatesOracle,
|
||||
deployAllMockAggregators,
|
||||
setInitialMarketRatesInRatesOracleByHelper,
|
||||
} from '../helpers/oracles-helpers';
|
||||
import {waitForTx} from '../helpers/misc-utils';
|
||||
import {enableReservesToBorrow, enableReservesAsCollateral} from '../helpers/init-helpers';
|
||||
import {
|
||||
initReservesByHelper,
|
||||
enableReservesToBorrowByHelper,
|
||||
enableReservesAsCollateralByHelper,
|
||||
} from '../helpers/init-helpers';
|
||||
import {AaveConfig} from '../config/aave';
|
||||
import {ZERO_ADDRESS} from '../helpers/constants';
|
||||
import {
|
||||
getLendingPool,
|
||||
getLendingPoolConfiguratorProxy,
|
||||
getPairsTokenAggregator,
|
||||
} from '../helpers/contracts-getters';
|
||||
|
||||
const MOCK_USD_PRICE_IN_WEI = AaveConfig.ProtocolGlobalParams.MockUsdPriceInWei;
|
||||
const ALL_ASSETS_INITIAL_PRICES = AaveConfig.Mocks.AllAssetsInitialPrices;
|
||||
|
@ -90,17 +98,11 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
|
||||
const lendingPoolImpl = await deployLendingPool();
|
||||
|
||||
console.log('Deployed lending pool, address:', lendingPoolImpl.address);
|
||||
await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address));
|
||||
|
||||
console.log('Added pool to addresses provider');
|
||||
|
||||
const address = await addressesProvider.getLendingPool();
|
||||
console.log('Address is ', address);
|
||||
const lendingPoolProxy = await getLendingPool(address);
|
||||
|
||||
console.log('implementation set, address:', lendingPoolProxy.address);
|
||||
|
||||
await insertContractAddressInDb(eContractid.LendingPool, lendingPoolProxy.address);
|
||||
|
||||
const lendingPoolConfiguratorImpl = await deployLendingPoolConfigurator();
|
||||
|
@ -115,6 +117,14 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
lendingPoolConfiguratorProxy.address
|
||||
);
|
||||
|
||||
// Deploy deployment helpers
|
||||
await deployStableAndVariableTokensHelper([lendingPoolProxy.address, addressesProvider.address]);
|
||||
await deployATokensAndRatesHelper([
|
||||
lendingPoolProxy.address,
|
||||
addressesProvider.address,
|
||||
lendingPoolConfiguratorProxy.address,
|
||||
]);
|
||||
|
||||
const fallbackOracle = await deployPriceOracle();
|
||||
await waitForTx(await fallbackOracle.setEthUsdPrice(MOCK_USD_PRICE_IN_WEI));
|
||||
await setInitialAssetPricesInOracle(
|
||||
|
@ -183,10 +193,11 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
const allReservesAddresses = {
|
||||
...tokensAddressesWithoutUsd,
|
||||
};
|
||||
await setInitialMarketRatesInRatesOracle(
|
||||
await setInitialMarketRatesInRatesOracleByHelper(
|
||||
LENDING_RATE_ORACLE_RATES_COMMON,
|
||||
allReservesAddresses,
|
||||
lendingRateOracle
|
||||
lendingRateOracle,
|
||||
aaveAdmin
|
||||
);
|
||||
|
||||
const {
|
||||
|
@ -204,30 +215,21 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
const testHelpers = await deployAaveProtocolTestHelpers(addressesProvider.address);
|
||||
|
||||
await insertContractAddressInDb(eContractid.AaveProtocolTestHelpers, testHelpers.address);
|
||||
const admin = await deployer.getAddress();
|
||||
|
||||
console.log('Initialize configuration');
|
||||
await initReserves(
|
||||
await initReservesByHelper(reservesParams, protoPoolReservesAddresses, admin, ZERO_ADDRESS);
|
||||
await enableReservesToBorrowByHelper(
|
||||
reservesParams,
|
||||
protoPoolReservesAddresses,
|
||||
addressesProvider,
|
||||
lendingPoolProxy,
|
||||
testHelpers,
|
||||
lendingPoolConfiguratorProxy,
|
||||
AavePools.proto,
|
||||
ZERO_ADDRESS,
|
||||
false
|
||||
admin
|
||||
);
|
||||
await enableReservesToBorrow(
|
||||
await enableReservesAsCollateralByHelper(
|
||||
reservesParams,
|
||||
protoPoolReservesAddresses,
|
||||
testHelpers,
|
||||
lendingPoolConfiguratorProxy
|
||||
);
|
||||
await enableReservesAsCollateral(
|
||||
reservesParams,
|
||||
protoPoolReservesAddresses,
|
||||
testHelpers,
|
||||
lendingPoolConfiguratorProxy
|
||||
admin
|
||||
);
|
||||
|
||||
const collateralManager = await deployLendingPoolCollateralManager();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import {TestEnv, makeSuite} from './helpers/make-suite';
|
||||
import {RAY, APPROVAL_AMOUNT_LENDING_POOL, ZERO_ADDRESS} from '../helpers/constants';
|
||||
import {convertToCurrencyDecimals} from '../helpers/contracts-helpers';
|
||||
import {ZERO_ADDRESS} from '../helpers/constants';
|
||||
import {ProtocolErrors} from '../helpers/types';
|
||||
|
||||
const {expect} = require('chai');
|
||||
|
|
|
@ -32,10 +32,11 @@ makeSuite('AToken: Permit', (testEnv: TestEnv) => {
|
|||
});
|
||||
|
||||
it('Get aDAI for tests', async () => {
|
||||
const {dai, deployer, pool} = testEnv;
|
||||
const {dai, pool, deployer} = testEnv;
|
||||
|
||||
await dai.mint(parseEther('20000'));
|
||||
await dai.approve(pool.address, parseEther('20000'));
|
||||
|
||||
await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0);
|
||||
});
|
||||
|
||||
|
|
|
@ -36,6 +36,10 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => {
|
|||
|
||||
await aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit);
|
||||
|
||||
const name = await aDai.name();
|
||||
|
||||
expect(name).to.be.equal('Aave interest bearing DAI');
|
||||
|
||||
const fromBalance = await aDai.balanceOf(users[0].address);
|
||||
const toBalance = await aDai.balanceOf(users[1].address);
|
||||
|
||||
|
@ -46,8 +50,8 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => {
|
|||
);
|
||||
});
|
||||
|
||||
it('User 0 deposits 1 WETH and user 1 tries to borrow, but the aTokens received as a transfer are not available as collateral (revert expected)', async () => {
|
||||
const {users, pool, weth} = testEnv;
|
||||
it('User 0 deposits 1 WETH and user 1 tries to borrow the WETH with the received DAI as collateral', async () => {
|
||||
const {users, pool, weth, helpersContract} = testEnv;
|
||||
const userAddress = await pool.signer.getAddress();
|
||||
|
||||
await weth.connect(users[0].signer).mint(await convertToCurrencyDecimals(weth.address, '1'));
|
||||
|
@ -57,26 +61,6 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => {
|
|||
await pool
|
||||
.connect(users[0].signer)
|
||||
.deposit(weth.address, ethers.utils.parseEther('1.0'), userAddress, '0');
|
||||
await expect(
|
||||
pool
|
||||
.connect(users[1].signer)
|
||||
.borrow(
|
||||
weth.address,
|
||||
ethers.utils.parseEther('0.1'),
|
||||
RateMode.Stable,
|
||||
AAVE_REFERRAL,
|
||||
users[1].address
|
||||
),
|
||||
COLLATERAL_BALANCE_IS_0
|
||||
).to.be.revertedWith(COLLATERAL_BALANCE_IS_0);
|
||||
});
|
||||
|
||||
it('User 1 sets the DAI as collateral and borrows, tries to transfer everything back to user 0 (revert expected)', async () => {
|
||||
const {users, pool, aDai, dai, weth} = testEnv;
|
||||
await pool.connect(users[1].signer).setUserUseReserveAsCollateral(dai.address, true);
|
||||
|
||||
const aDAItoTransfer = await convertToCurrencyDecimals(dai.address, '1000');
|
||||
|
||||
await pool
|
||||
.connect(users[1].signer)
|
||||
.borrow(
|
||||
|
@ -87,9 +71,34 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => {
|
|||
users[1].address
|
||||
);
|
||||
|
||||
const userReserveData = await helpersContract.getUserReserveData(
|
||||
weth.address,
|
||||
users[1].address
|
||||
);
|
||||
|
||||
expect(userReserveData.currentStableDebt.toString()).to.be.eq(ethers.utils.parseEther('0.1'));
|
||||
});
|
||||
|
||||
it('User 1 tries to transfer all the DAI used as collateral back to user 0 (revert expected)', async () => {
|
||||
const {users, pool, aDai, dai, weth} = testEnv;
|
||||
|
||||
const aDAItoTransfer = await convertToCurrencyDecimals(dai.address, '1000');
|
||||
|
||||
await expect(
|
||||
aDai.connect(users[1].signer).transfer(users[0].address, aDAItoTransfer),
|
||||
TRANSFER_NOT_ALLOWED
|
||||
).to.be.revertedWith(TRANSFER_NOT_ALLOWED);
|
||||
});
|
||||
|
||||
it('User 1 tries to transfer a small amount of DAI used as collateral back to user 0', async () => {
|
||||
const {users, pool, aDai, dai, weth} = testEnv;
|
||||
|
||||
const aDAItoTransfer = await convertToCurrencyDecimals(dai.address, '100');
|
||||
|
||||
await aDai.connect(users[1].signer).transfer(users[0].address, aDAItoTransfer);
|
||||
|
||||
const user0Balance = await aDai.balanceOf(users[0].address);
|
||||
|
||||
expect(user0Balance.toString()).to.be.eq(aDAItoTransfer.toString());
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,7 +10,63 @@ const APPROVAL_AMOUNT_LENDING_POOL =
|
|||
const {expect} = require('chai');
|
||||
|
||||
makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
||||
const {CALLER_NOT_AAVE_ADMIN, RESERVE_LIQUIDITY_NOT_0} = ProtocolErrors;
|
||||
const {
|
||||
CALLER_NOT_AAVE_ADMIN,
|
||||
RESERVE_LIQUIDITY_NOT_0,
|
||||
INVALID_LTV,
|
||||
INVALID_LIQ_THRESHOLD,
|
||||
INVALID_LIQ_BONUS,
|
||||
INVALID_DECIMALS,
|
||||
INVALID_RESERVE_FACTOR,
|
||||
} = ProtocolErrors;
|
||||
|
||||
it('Reverts trying to set an invalid LTV', async () => {
|
||||
const {configurator, weth} = testEnv;
|
||||
|
||||
const invalidLtv = 65536;
|
||||
|
||||
await expect(configurator.setLtv(weth.address, invalidLtv)).to.be.revertedWith(INVALID_LTV);
|
||||
});
|
||||
|
||||
it('Reverts trying to set an invalid liquidation threshold', async () => {
|
||||
const {configurator, weth} = testEnv;
|
||||
|
||||
const invalidLiqThreshold = 65536;
|
||||
|
||||
await expect(
|
||||
configurator.setLiquidationThreshold(weth.address, invalidLiqThreshold)
|
||||
).to.be.revertedWith(INVALID_LIQ_THRESHOLD);
|
||||
});
|
||||
|
||||
it('Reverts trying to set an invalid liquidation bonus', async () => {
|
||||
const {configurator, weth} = testEnv;
|
||||
|
||||
const invalidLiqBonus = 65536;
|
||||
|
||||
await expect(
|
||||
configurator.setLiquidationBonus(weth.address, invalidLiqBonus)
|
||||
).to.be.revertedWith(INVALID_LIQ_BONUS);
|
||||
});
|
||||
|
||||
it('Reverts trying to set an invalid reserve decimals', async () => {
|
||||
const {configurator, weth} = testEnv;
|
||||
|
||||
const invalidDecimals = 256;
|
||||
|
||||
await expect(configurator.setReserveDecimals(weth.address, invalidDecimals)).to.be.revertedWith(
|
||||
INVALID_DECIMALS
|
||||
);
|
||||
});
|
||||
|
||||
it('Reverts trying to set an invalid reserve factor', async () => {
|
||||
const {configurator, weth} = testEnv;
|
||||
|
||||
const invalidReserveFactor = 65536;
|
||||
|
||||
await expect(
|
||||
configurator.setReserveFactor(weth.address, invalidReserveFactor)
|
||||
).to.be.revertedWith(INVALID_RESERVE_FACTOR);
|
||||
});
|
||||
|
||||
it('Deactivates the ETH reserve', async () => {
|
||||
const {configurator, weth, helpersContract} = testEnv;
|
||||
|
|
|
@ -2,16 +2,13 @@ import BigNumber from 'bignumber.js';
|
|||
|
||||
import {TestEnv, makeSuite} from './helpers/make-suite';
|
||||
import {APPROVAL_AMOUNT_LENDING_POOL, oneRay} from '../helpers/constants';
|
||||
import {
|
||||
convertToCurrencyDecimals,
|
||||
getMockFlashLoanReceiver,
|
||||
getContract,
|
||||
} from '../helpers/contracts-helpers';
|
||||
import {convertToCurrencyDecimals, getContract} from '../helpers/contracts-helpers';
|
||||
import {ethers} from 'ethers';
|
||||
import {MockFlashLoanReceiver} from '../types/MockFlashLoanReceiver';
|
||||
import {ProtocolErrors, eContractid} from '../helpers/types';
|
||||
import {VariableDebtToken} from '../types/VariableDebtToken';
|
||||
import {StableDebtToken} from '../types/StableDebtToken';
|
||||
import {getMockFlashLoanReceiver} from '../helpers/contracts-getters';
|
||||
|
||||
const {expect} = require('chai');
|
||||
|
||||
|
@ -25,6 +22,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
SAFEERC20_LOWLEVEL_CALL,
|
||||
IS_PAUSED,
|
||||
INVALID_FLASH_LOAN_EXECUTOR_RETURN,
|
||||
BORROW_ALLOWANCE_ARE_NOT_ENOUGH,
|
||||
} = ProtocolErrors;
|
||||
|
||||
before(async () => {
|
||||
|
@ -51,6 +49,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
[weth.address],
|
||||
[ethers.utils.parseEther('0.8')],
|
||||
0,
|
||||
_mockFlashLoanReceiver.address,
|
||||
'0x10',
|
||||
'0'
|
||||
);
|
||||
|
@ -80,6 +79,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
[weth.address],
|
||||
['1000720000000000000'],
|
||||
0,
|
||||
_mockFlashLoanReceiver.address,
|
||||
'0x10',
|
||||
'0'
|
||||
);
|
||||
|
@ -111,6 +111,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
[weth.address],
|
||||
[ethers.utils.parseEther('0.8')],
|
||||
0,
|
||||
caller.address,
|
||||
'0x10',
|
||||
'0'
|
||||
)
|
||||
|
@ -131,6 +132,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
[weth.address],
|
||||
[ethers.utils.parseEther('0.8')],
|
||||
0,
|
||||
caller.address,
|
||||
'0x10',
|
||||
'0'
|
||||
)
|
||||
|
@ -151,6 +153,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
[weth.address],
|
||||
[ethers.utils.parseEther('0.8')],
|
||||
4,
|
||||
caller.address,
|
||||
'0x10',
|
||||
'0'
|
||||
)
|
||||
|
@ -179,6 +182,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
[weth.address],
|
||||
[ethers.utils.parseEther('0.8')],
|
||||
2,
|
||||
caller.address,
|
||||
'0x10',
|
||||
'0'
|
||||
);
|
||||
|
@ -197,14 +201,16 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
});
|
||||
|
||||
it('tries to take a flashloan that is bigger than the available liquidity (revert expected)', async () => {
|
||||
const {pool, weth} = testEnv;
|
||||
const {pool, weth, users} = testEnv;
|
||||
const caller = users[1];
|
||||
|
||||
await expect(
|
||||
pool.flashLoan(
|
||||
pool.connect(caller.signer).flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
[weth.address],
|
||||
['1004415000000000000'], //slightly higher than the available liquidity
|
||||
2,
|
||||
caller.address,
|
||||
'0x10',
|
||||
'0'
|
||||
),
|
||||
|
@ -213,10 +219,19 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
});
|
||||
|
||||
it('tries to take a flashloan using a non contract address as receiver (revert expected)', async () => {
|
||||
const {pool, deployer, weth} = testEnv;
|
||||
const {pool, deployer, weth, users} = testEnv;
|
||||
const caller = users[1];
|
||||
|
||||
await expect(
|
||||
pool.flashLoan(deployer.address, [weth.address], ['1000000000000000000'], 2, '0x10', '0')
|
||||
pool.flashLoan(
|
||||
deployer.address,
|
||||
[weth.address],
|
||||
['1000000000000000000'],
|
||||
2,
|
||||
caller.address,
|
||||
'0x10',
|
||||
'0'
|
||||
)
|
||||
).to.be.reverted;
|
||||
});
|
||||
|
||||
|
@ -245,6 +260,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
[usdc.address],
|
||||
[flashloanAmount],
|
||||
0,
|
||||
_mockFlashLoanReceiver.address,
|
||||
'0x10',
|
||||
'0'
|
||||
);
|
||||
|
@ -287,6 +303,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
[usdc.address],
|
||||
[flashloanAmount],
|
||||
2,
|
||||
caller.address,
|
||||
'0x10',
|
||||
'0'
|
||||
)
|
||||
|
@ -312,7 +329,15 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
|
||||
await pool
|
||||
.connect(caller.signer)
|
||||
.flashLoan(_mockFlashLoanReceiver.address, [usdc.address], [flashloanAmount], 2, '0x10', '0');
|
||||
.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
[usdc.address],
|
||||
[flashloanAmount],
|
||||
2,
|
||||
caller.address,
|
||||
'0x10',
|
||||
'0'
|
||||
);
|
||||
const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(
|
||||
usdc.address
|
||||
);
|
||||
|
@ -347,7 +372,15 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
await expect(
|
||||
pool
|
||||
.connect(caller.signer)
|
||||
.flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 0, '0x10', '0')
|
||||
.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
[weth.address],
|
||||
[flashAmount],
|
||||
0,
|
||||
caller.address,
|
||||
'0x10',
|
||||
'0'
|
||||
)
|
||||
).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL);
|
||||
});
|
||||
|
||||
|
@ -362,7 +395,15 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
|
||||
await pool
|
||||
.connect(caller.signer)
|
||||
.flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 1, '0x10', '0');
|
||||
.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
[weth.address],
|
||||
[flashAmount],
|
||||
1,
|
||||
caller.address,
|
||||
'0x10',
|
||||
'0'
|
||||
);
|
||||
|
||||
const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address);
|
||||
|
||||
|
@ -375,4 +416,82 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
|
||||
expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt');
|
||||
});
|
||||
|
||||
it('Caller takes a WETH flashloan with mode = 1 onBehalfOf user without allowance', async () => {
|
||||
const {dai, pool, weth, users, helpersContract} = testEnv;
|
||||
|
||||
const caller = users[5];
|
||||
const onBehalfOf = users[4];
|
||||
|
||||
// Deposit 1000 dai for onBehalfOf user
|
||||
await dai.connect(onBehalfOf.signer).mint(await convertToCurrencyDecimals(dai.address, '1000'));
|
||||
|
||||
await dai.connect(onBehalfOf.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL);
|
||||
|
||||
const amountToDeposit = await convertToCurrencyDecimals(dai.address, '1000');
|
||||
|
||||
await pool
|
||||
.connect(onBehalfOf.signer)
|
||||
.deposit(dai.address, amountToDeposit, onBehalfOf.address, '0');
|
||||
|
||||
const flashAmount = ethers.utils.parseEther('0.8');
|
||||
|
||||
await _mockFlashLoanReceiver.setFailExecutionTransfer(true);
|
||||
|
||||
await expect(
|
||||
pool
|
||||
.connect(caller.signer)
|
||||
.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
[weth.address],
|
||||
[flashAmount],
|
||||
1,
|
||||
onBehalfOf.address,
|
||||
'0x10',
|
||||
'0'
|
||||
)
|
||||
).to.be.revertedWith(BORROW_ALLOWANCE_ARE_NOT_ENOUGH);
|
||||
});
|
||||
|
||||
it('Caller takes a WETH flashloan with mode = 1 onBehalfOf user with allowance. A loan for onBehalfOf is creatd.', async () => {
|
||||
const {dai, pool, weth, users, helpersContract} = testEnv;
|
||||
|
||||
const caller = users[5];
|
||||
const onBehalfOf = users[4];
|
||||
|
||||
const flashAmount = ethers.utils.parseEther('0.8');
|
||||
|
||||
// Deposited for onBehalfOf user already, delegate borrow allowance
|
||||
await pool
|
||||
.connect(onBehalfOf.signer)
|
||||
.delegateBorrowAllowance(weth.address, caller.address, 1, flashAmount);
|
||||
|
||||
await _mockFlashLoanReceiver.setFailExecutionTransfer(true);
|
||||
|
||||
await pool
|
||||
.connect(caller.signer)
|
||||
.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
[weth.address],
|
||||
[flashAmount],
|
||||
1,
|
||||
onBehalfOf.address,
|
||||
'0x10',
|
||||
'0'
|
||||
);
|
||||
|
||||
const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address);
|
||||
|
||||
const wethDebtToken = await getContract<StableDebtToken>(
|
||||
eContractid.VariableDebtToken,
|
||||
stableDebtTokenAddress
|
||||
);
|
||||
|
||||
const onBehalfOfDebt = await wethDebtToken.balanceOf(onBehalfOf.address);
|
||||
|
||||
expect(onBehalfOfDebt.toString()).to.be.equal(
|
||||
'800000000000000000',
|
||||
'Invalid onBehalfOf user debt'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,11 +17,8 @@ import {
|
|||
} from './utils/calculations';
|
||||
import {getReserveAddressFromSymbol, getReserveData, getUserData} from './utils/helpers';
|
||||
|
||||
import {
|
||||
convertToCurrencyDecimals,
|
||||
getAToken,
|
||||
getMintableErc20,
|
||||
} from '../../helpers/contracts-helpers';
|
||||
import {convertToCurrencyDecimals} from '../../helpers/contracts-helpers';
|
||||
import {getAToken, getMintableErc20} from '../../helpers/contracts-getters';
|
||||
import {MAX_UINT_AMOUNT, ONE_YEAR} from '../../helpers/constants';
|
||||
import {SignerWithAddress, TestEnv} from './make-suite';
|
||||
import {BRE, increaseTime, timeLatest, waitForTx} from '../../helpers/misc-utils';
|
||||
|
@ -31,7 +28,6 @@ import {ReserveData, UserReserveData} from './utils/interfaces';
|
|||
import {ContractReceipt} from 'ethers';
|
||||
import {AToken} from '../../types/AToken';
|
||||
import {RateMode, tEthereumAddress} from '../../helpers/types';
|
||||
import {time} from 'console';
|
||||
|
||||
const {expect} = chai;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import {evmRevert, evmSnapshot, BRE} from '../../helpers/misc-utils';
|
||||
import {Signer} from 'ethers';
|
||||
import {
|
||||
getEthersSigners,
|
||||
getLendingPool,
|
||||
getLendingPoolAddressesProvider,
|
||||
getAaveProtocolTestHelpers,
|
||||
|
@ -10,7 +9,7 @@ import {
|
|||
getLendingPoolConfiguratorProxy,
|
||||
getPriceOracle,
|
||||
getLendingPoolAddressesProviderRegistry,
|
||||
} from '../../helpers/contracts-helpers';
|
||||
} from '../../helpers/contracts-getters';
|
||||
import {tEthereumAddress} from '../../helpers/types';
|
||||
import {LendingPool} from '../../types/LendingPool';
|
||||
import {AaveProtocolTestHelpers} from '../../types/AaveProtocolTestHelpers';
|
||||
|
@ -25,6 +24,7 @@ import {almostEqual} from './almost-equal';
|
|||
import {PriceOracle} from '../../types/PriceOracle';
|
||||
import {LendingPoolAddressesProvider} from '../../types/LendingPoolAddressesProvider';
|
||||
import {LendingPoolAddressesProviderRegistry} from '../../types/LendingPoolAddressesProviderRegistry';
|
||||
import {getEthersSigners} from '../../helpers/contracts-helpers';
|
||||
chai.use(bignumberChai());
|
||||
chai.use(almostEqual());
|
||||
|
||||
|
@ -40,7 +40,7 @@ export interface TestEnv {
|
|||
oracle: PriceOracle;
|
||||
helpersContract: AaveProtocolTestHelpers;
|
||||
weth: MintableERC20;
|
||||
aEth: AToken;
|
||||
aWETH: AToken;
|
||||
dai: MintableERC20;
|
||||
aDai: AToken;
|
||||
usdc: MintableERC20;
|
||||
|
@ -64,7 +64,7 @@ const testEnv: TestEnv = {
|
|||
helpersContract: {} as AaveProtocolTestHelpers,
|
||||
oracle: {} as PriceOracle,
|
||||
weth: {} as MintableERC20,
|
||||
aEth: {} as AToken,
|
||||
aWETH: {} as AToken,
|
||||
dai: {} as MintableERC20,
|
||||
aDai: {} as AToken,
|
||||
usdc: {} as MintableERC20,
|
||||
|
@ -88,10 +88,8 @@ export async function initializeMakeSuite() {
|
|||
}
|
||||
testEnv.deployer = deployer;
|
||||
testEnv.pool = await getLendingPool();
|
||||
console.log('Pool loaded');
|
||||
|
||||
testEnv.configurator = await getLendingPoolConfiguratorProxy();
|
||||
console.log('Configurator loaded');
|
||||
|
||||
testEnv.oracle = await getPriceOracle();
|
||||
testEnv.addressesProvider = await getLendingPoolAddressesProvider();
|
||||
|
@ -99,13 +97,11 @@ export async function initializeMakeSuite() {
|
|||
|
||||
testEnv.helpersContract = await getAaveProtocolTestHelpers();
|
||||
|
||||
const aDaiAddress = (await testEnv.helpersContract.getAllATokens()).find(
|
||||
(aToken) => aToken.symbol === 'aDAI'
|
||||
)?.tokenAddress;
|
||||
const allTokens = await testEnv.helpersContract.getAllATokens();
|
||||
|
||||
const aEthAddress = (await testEnv.helpersContract.getAllATokens()).find(
|
||||
(aToken) => aToken.symbol === 'aETH'
|
||||
)?.tokenAddress;
|
||||
const aDaiAddress = allTokens.find((aToken) => aToken.symbol === 'aDAI')?.tokenAddress;
|
||||
|
||||
const aWEthAddress = allTokens.find((aToken) => aToken.symbol === 'aWETH')?.tokenAddress;
|
||||
|
||||
const reservesTokens = await testEnv.helpersContract.getAllReservesTokens();
|
||||
|
||||
|
@ -114,7 +110,7 @@ export async function initializeMakeSuite() {
|
|||
const lendAddress = reservesTokens.find((token) => token.symbol === 'LEND')?.tokenAddress;
|
||||
const wethAddress = reservesTokens.find((token) => token.symbol === 'WETH')?.tokenAddress;
|
||||
|
||||
if (!aDaiAddress || !aEthAddress) {
|
||||
if (!aDaiAddress || !aWEthAddress) {
|
||||
console.log(`atoken-modifiers.spec: aTokens not correctly initialized`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
@ -124,7 +120,7 @@ export async function initializeMakeSuite() {
|
|||
}
|
||||
|
||||
testEnv.aDai = await getAToken(aDaiAddress);
|
||||
testEnv.aEth = await getAToken(aEthAddress);
|
||||
testEnv.aWETH = await getAToken(aWEthAddress);
|
||||
|
||||
testEnv.dai = await getMintableErc20(daiAddress);
|
||||
testEnv.usdc = await getMintableErc20(usdcAddress);
|
||||
|
|
|
@ -5,7 +5,6 @@ import {
|
|||
MAX_UINT_AMOUNT,
|
||||
OPTIMAL_UTILIZATION_RATE,
|
||||
EXCESS_UTILIZATION_RATE,
|
||||
ZERO_ADDRESS,
|
||||
} from '../../../helpers/constants';
|
||||
import {IReserveParams, iAavePoolAssets, RateMode, tEthereumAddress} from '../../../helpers/types';
|
||||
import './math';
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
getAToken,
|
||||
getStableDebtToken,
|
||||
getVariableDebtToken,
|
||||
} from '../../../helpers/contracts-helpers';
|
||||
} from '../../../helpers/contracts-getters';
|
||||
import {tEthereumAddress} from '../../../helpers/types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import {getDb, BRE} from '../../../helpers/misc-utils';
|
||||
|
@ -27,7 +27,7 @@ export const getReserveData = async (
|
|||
const stableDebtToken = await getStableDebtToken(tokenAddresses.stableDebtTokenAddress);
|
||||
const variableDebtToken = await getVariableDebtToken(tokenAddresses.variableDebtTokenAddress);
|
||||
|
||||
const [principalStableDebt] = await stableDebtToken.getSupplyData();
|
||||
const {0: principalStableDebt} = await stableDebtToken.getSupplyData();
|
||||
const totalStableDebtLastUpdated = await stableDebtToken.getTotalSupplyLastUpdated();
|
||||
|
||||
const scaledVariableDebt = await variableDebtToken.scaledTotalSupply();
|
||||
|
|
|
@ -5,7 +5,7 @@ import {ProtocolErrors} from '../helpers/types';
|
|||
import {ethers} from 'ethers';
|
||||
import {ZERO_ADDRESS} from '../helpers/constants';
|
||||
import {waitForTx} from '../helpers/misc-utils';
|
||||
import {deployLendingPool} from '../helpers/contracts-helpers';
|
||||
import {deployLendingPool} from '../helpers/contracts-deployments';
|
||||
|
||||
const {utils} = ethers;
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import {makeSuite, TestEnv} from './helpers/make-suite';
|
||||
import {ProtocolErrors, RateMode} from '../helpers/types';
|
||||
import {APPROVAL_AMOUNT_LENDING_POOL, oneEther} from '../helpers/constants';
|
||||
import {convertToCurrencyDecimals, getMockFlashLoanReceiver} from '../helpers/contracts-helpers';
|
||||
import {convertToCurrencyDecimals} from '../helpers/contracts-helpers';
|
||||
import {parseEther, parseUnits} from 'ethers/lib/utils';
|
||||
import {BigNumber} from 'bignumber.js';
|
||||
import {MockFlashLoanReceiver} from '../types/MockFlashLoanReceiver';
|
||||
import {getMockFlashLoanReceiver} from '../helpers/contracts-getters';
|
||||
|
||||
const {expect} = require('chai');
|
||||
|
||||
|
@ -186,7 +187,15 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
await expect(
|
||||
pool
|
||||
.connect(caller.signer)
|
||||
.flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 1, '0x10', '0')
|
||||
.flashLoan(
|
||||
_mockFlashLoanReceiver.address,
|
||||
[weth.address],
|
||||
[flashAmount],
|
||||
1,
|
||||
caller.address,
|
||||
'0x10',
|
||||
'0'
|
||||
)
|
||||
).revertedWith(IS_PAUSED);
|
||||
|
||||
// Unpause pool
|
||||
|
|
|
@ -152,7 +152,7 @@
|
|||
// });
|
||||
|
||||
// it('unfreezes the reserve, user deposits 1 ETH, freezes the reserve, check that the user can redeem', async () => {
|
||||
// const {aETH} = _aTokenInstances;
|
||||
// const {aWETH} = _aTokenInstances;
|
||||
|
||||
// //unfreezes the reserve
|
||||
// await _lendingPoolConfiguratorInstance.unfreezeReserve(ETHEREUM_ADDRESS);
|
||||
|
@ -165,13 +165,13 @@
|
|||
// //freezes the reserve
|
||||
// await _lendingPoolConfiguratorInstance.freezeReserve(ETHEREUM_ADDRESS);
|
||||
|
||||
// const balance = await aETH.balanceOf(deployer);
|
||||
// const balance = await aWETH.balanceOf(deployer);
|
||||
|
||||
// await aETH.redeem(balance);
|
||||
// await aWETH.redeem(balance);
|
||||
// });
|
||||
|
||||
// it('unfreezes the reserve, user 0 deposits 100 DAI, user 1 deposits 1 ETH and borrows 50 DAI, freezes the reserve, checks that the user 1 can repay', async () => {
|
||||
// const {aETH, aDAI} = _aTokenInstances;
|
||||
// const {aWETH, aDAI} = _aTokenInstances;
|
||||
// const {DAI} = _tokenInstances;
|
||||
|
||||
// //unfreezes the reserve
|
||||
|
@ -209,7 +209,7 @@
|
|||
// });
|
||||
|
||||
// it('Check that liquidationCall can be executed on a freezed reserve', async () => {
|
||||
// const {aETH, aDAI} = _aTokenInstances;
|
||||
// const {aWETH, aDAI} = _aTokenInstances;
|
||||
// const {DAI} = _tokenInstances;
|
||||
|
||||
// //user 2 tries to liquidate
|
||||
|
@ -228,7 +228,7 @@
|
|||
// });
|
||||
|
||||
// it('Check that rebalanceStableBorrowRate can be executed on a freezed reserve', async () => {
|
||||
// const {aETH, aDAI} = _aTokenInstances;
|
||||
// const {aWETH, aDAI} = _aTokenInstances;
|
||||
// const {DAI} = _tokenInstances;
|
||||
|
||||
// //user 2 tries to liquidate
|
||||
|
|
|
@ -34,6 +34,9 @@ makeSuite('Stable debt token tests', (testEnv: TestEnv) => {
|
|||
daiStableDebtTokenAddress
|
||||
);
|
||||
|
||||
const name = await stableDebtContract.name();
|
||||
|
||||
expect(name).to.be.equal('Aave stable debt bearing DAI');
|
||||
await expect(stableDebtContract.burn(deployer.address, '1')).to.be.revertedWith(
|
||||
CALLER_MUST_BE_LENDING_POOL
|
||||
);
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
import {expect} from 'chai';
|
||||
import {makeSuite, TestEnv} from './helpers/make-suite';
|
||||
import {ProtocolErrors, eContractid} from '../helpers/types';
|
||||
import {
|
||||
deployGenericAToken,
|
||||
getAToken,
|
||||
deployContract,
|
||||
getContract,
|
||||
} from '../helpers/contracts-helpers';
|
||||
import {deployContract, getContract} from '../helpers/contracts-helpers';
|
||||
import {MockAToken} from '../types/MockAToken';
|
||||
import {MockStableDebtToken} from '../types/MockStableDebtToken';
|
||||
import {MockVariableDebtToken} from '../types/MockVariableDebtToken';
|
||||
import {ZERO_ADDRESS} from '../helpers/constants';
|
||||
import {getAToken} from '../helpers/contracts-getters';
|
||||
|
||||
makeSuite('Upgradeability', (testEnv: TestEnv) => {
|
||||
const {CALLER_NOT_AAVE_ADMIN} = ProtocolErrors;
|
||||
|
|
Loading…
Reference in New Issue
Block a user