mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Merge master
This commit is contained in:
commit
95b94e46e2
|
@ -11,7 +11,7 @@ usePlugin('buidler-typechain');
|
|||
usePlugin('solidity-coverage');
|
||||
usePlugin('@nomiclabs/buidler-waffle');
|
||||
usePlugin('@nomiclabs/buidler-etherscan');
|
||||
//usePlugin('buidler-gas-reporter');
|
||||
usePlugin('buidler-gas-reporter');
|
||||
|
||||
const SKIP_LOAD = process.env.SKIP_LOAD === 'true';
|
||||
const DEFAULT_BLOCK_GAS_LIMIT = 12000000;
|
||||
|
|
|
@ -54,6 +54,8 @@ contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesP
|
|||
* @param provider the pool address to be registered
|
||||
**/
|
||||
function registerAddressesProvider(address provider, uint256 id) external override onlyOwner {
|
||||
require(id != 0, Errors.INVALID_ADDRESSES_PROVIDER_ID);
|
||||
|
||||
_addressesProviders[provider] = id;
|
||||
_addToAddressesProvidersList(provider);
|
||||
emit AddressesProviderRegistered(provider);
|
||||
|
|
|
@ -66,18 +66,19 @@ contract DeployATokensAndRates {
|
|||
}
|
||||
|
||||
function initReserve(
|
||||
address[] calldata tokens,
|
||||
address[] calldata stables,
|
||||
address[] calldata variables,
|
||||
address[] calldata aTokens,
|
||||
address[] calldata strategies,
|
||||
uint8[] calldata reserveDecimals
|
||||
) external {
|
||||
// TODO require(check lenghts)
|
||||
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 < tokens.length; i++) {
|
||||
for (uint256 i = 0; i < stables.length; i++) {
|
||||
LendingPoolConfigurator(poolConfigurator).initReserve(
|
||||
tokens[i],
|
||||
aTokens[i],
|
||||
stables[i],
|
||||
variables[i],
|
||||
|
|
|
@ -162,7 +162,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
|
|||
_stableRateSlope1.rayMul(utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE))
|
||||
);
|
||||
vars.currentVariableBorrowRate = _baseVariableBorrowRate.add(
|
||||
utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE).rayMul(_variableRateSlope1)
|
||||
utilizationRate.rayMul(_variableRateSlope1).rayDiv(OPTIMAL_UTILIZATION_RATE)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -267,7 +267,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
? stableDebt
|
||||
: variableDebt;
|
||||
|
||||
if (amount != type(uint256).max && amount < paybackAmount) {
|
||||
if (amount < paybackAmount) {
|
||||
paybackAmount = amount;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
|
||||
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
||||
import {ILendingPool} from '../interfaces/ILendingPool.sol';
|
||||
import {ITokenConfiguration} from '../tokenization/interfaces/ITokenConfiguration.sol';
|
||||
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
|
||||
import {Errors} from '../libraries/helpers/Errors.sol';
|
||||
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
|
||||
|
@ -200,7 +201,6 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
|
||||
/**
|
||||
* @dev initializes a reserve
|
||||
* @param asset the address of the reserve to be initialized
|
||||
* @param aTokenImpl the address of the aToken contract implementation
|
||||
* @param stableDebtTokenImpl the address of the stable debt token contract
|
||||
* @param variableDebtTokenImpl the address of the variable debt token contract
|
||||
|
@ -208,13 +208,35 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @param interestRateStrategyAddress the address of the interest rate strategy contract for this reserve
|
||||
**/
|
||||
function initReserve(
|
||||
address asset,
|
||||
address aTokenImpl,
|
||||
address stableDebtTokenImpl,
|
||||
address variableDebtTokenImpl,
|
||||
uint8 underlyingAssetDecimals,
|
||||
address interestRateStrategyAddress
|
||||
) public onlyAaveAdmin {
|
||||
address asset = ITokenConfiguration(aTokenImpl).UNDERLYING_ASSET_ADDRESS();
|
||||
|
||||
require(
|
||||
address(pool) == ITokenConfiguration(aTokenImpl).POOL(),
|
||||
Errors.INVALID_ATOKEN_POOL_ADDRESS
|
||||
);
|
||||
require(
|
||||
address(pool) == ITokenConfiguration(stableDebtTokenImpl).POOL(),
|
||||
Errors.INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS
|
||||
);
|
||||
require(
|
||||
address(pool) == ITokenConfiguration(variableDebtTokenImpl).POOL(),
|
||||
Errors.INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS
|
||||
);
|
||||
require(
|
||||
asset == ITokenConfiguration(stableDebtTokenImpl).UNDERLYING_ASSET_ADDRESS(),
|
||||
Errors.INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS
|
||||
);
|
||||
require(
|
||||
asset == ITokenConfiguration(variableDebtTokenImpl).UNDERLYING_ASSET_ADDRESS(),
|
||||
Errors.INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS
|
||||
);
|
||||
|
||||
address aTokenProxyAddress = _initTokenWithProxy(aTokenImpl, underlyingAssetDecimals);
|
||||
|
||||
address stableDebtTokenProxyAddress = _initTokenWithProxy(
|
||||
|
|
|
@ -50,8 +50,8 @@ library Errors {
|
|||
string public constant CALLER_MUST_BE_LENDING_POOL = '28'; // 'The caller of this function must be a lending pool'
|
||||
string public constant CANNOT_GIVE_ALLOWANCE_TO_HIMSELF = '30'; // 'User cannot give allowance to himself'
|
||||
string public constant TRANSFER_AMOUNT_NOT_GT_0 = '31'; // 'Transferred amount needs to be greater than zero'
|
||||
string public constant INVALID_MINT_AMOUNT = '53'; //invalid amount to mint
|
||||
string public constant INVALID_BURN_AMOUNT = '54'; //invalid amount to burn
|
||||
string public constant INVALID_MINT_AMOUNT = '61'; //invalid amount to mint
|
||||
string public constant INVALID_BURN_AMOUNT = '62'; //invalid amount to burn
|
||||
|
||||
// require error messages - ReserveLogic
|
||||
string public constant RESERVE_ALREADY_INITIALIZED = '34'; // 'Reserve has already been initialized'
|
||||
|
@ -64,9 +64,15 @@ library Errors {
|
|||
//require error messages - LendingPoolConfiguration
|
||||
string public constant CALLER_NOT_AAVE_ADMIN = '35'; // 'The caller must be the aave admin'
|
||||
string public constant RESERVE_LIQUIDITY_NOT_0 = '36'; // 'The liquidity of the reserve needs to be 0'
|
||||
string public constant INVALID_ATOKEN_POOL_ADDRESS = '63'; // the lending pool in the aToken implementation is not configured correctly
|
||||
string public constant INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS = '64'; // the lending pool in the stable debt token implementation is not configured correctly
|
||||
string public constant INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS = '65'; // the lending pool in the variable debt token implementation is not configured correctly
|
||||
string public constant INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '66'; // the underlying asset in the stable debt token implementation is not configured correctly
|
||||
string public constant INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '67'; // the underlying asset in the variable debt token implementation is not configured correctly
|
||||
|
||||
//require error messages - LendingPoolAddressesProviderRegistry
|
||||
string public constant PROVIDER_NOT_REGISTERED = '37'; // 'Provider is not registered'
|
||||
string public constant INVALID_ADDRESSES_PROVIDER_ID = '68'; // the addresses provider id needs to be greater than 0
|
||||
|
||||
//return error messages - LendingPoolCollateralManager
|
||||
string public constant HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '38'; // 'Health factor is not below the threshold'
|
||||
|
|
|
@ -359,7 +359,9 @@ library ReserveLogic {
|
|||
|
||||
vars.amountToMint = vars.totalDebtAccrued.percentMul(vars.reserveFactor);
|
||||
|
||||
IAToken(reserve.aTokenAddress).mintToTreasury(vars.amountToMint, newLiquidityIndex);
|
||||
if (vars.amountToMint != 0) {
|
||||
IAToken(reserve.aTokenAddress).mintToTreasury(vars.amountToMint, newLiquidityIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -58,13 +58,9 @@ library WadRayMath {
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint256 result = a * b;
|
||||
uint256 result = a * b + halfWAD;
|
||||
|
||||
require(result / a == b, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
result += halfWAD;
|
||||
|
||||
require(result >= halfWAD, Errors.ADDITION_OVERFLOW);
|
||||
require(result >= halfWAD && (result - halfWAD) / a == b, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
return result / WAD;
|
||||
}
|
||||
|
@ -80,13 +76,9 @@ library WadRayMath {
|
|||
|
||||
uint256 halfB = b / 2;
|
||||
|
||||
uint256 result = a * WAD;
|
||||
uint256 result = a * WAD + halfB;
|
||||
|
||||
require(result / WAD == a, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
result += halfB;
|
||||
|
||||
require(result >= halfB, Errors.ADDITION_OVERFLOW);
|
||||
require(result >= halfB && (result - halfB) / WAD == a, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
return result / b;
|
||||
}
|
||||
|
@ -102,13 +94,9 @@ library WadRayMath {
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint256 result = a * b;
|
||||
uint256 result = a * b + halfRAY;
|
||||
|
||||
require(result / a == b, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
result += halfRAY;
|
||||
|
||||
require(result >= halfRAY, Errors.ADDITION_OVERFLOW);
|
||||
require(result >= halfRAY && (result - halfRAY) / a == b, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
return result / RAY;
|
||||
}
|
||||
|
@ -124,13 +112,9 @@ library WadRayMath {
|
|||
|
||||
uint256 halfB = b / 2;
|
||||
|
||||
uint256 result = a * RAY;
|
||||
uint256 result = a * RAY + halfB;
|
||||
|
||||
require(result / RAY == a, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
result += halfB;
|
||||
|
||||
require(result >= halfB, Errors.ADDITION_OVERFLOW);
|
||||
require(result >= halfB && (result - halfB) / RAY == a, Errors.MULTIPLICATION_OVERFLOW);
|
||||
|
||||
return result / b;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
pragma solidity ^0.6.8;
|
||||
|
||||
import {IncentivizedERC20} from './IncentivizedERC20.sol';
|
||||
import {LendingPool} from '../lendingpool/LendingPool.sol';
|
||||
import {ILendingPool} from '../interfaces/ILendingPool.sol';
|
||||
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
|
||||
import {Errors} from '../libraries/helpers/Errors.sol';
|
||||
import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol';
|
||||
|
@ -32,7 +32,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
|
|||
uint256 public constant ATOKEN_REVISION = 0x1;
|
||||
address public immutable UNDERLYING_ASSET_ADDRESS;
|
||||
address public immutable RESERVE_TREASURY_ADDRESS;
|
||||
LendingPool public immutable POOL;
|
||||
ILendingPool public immutable POOL;
|
||||
|
||||
/// @dev owner => next valid nonce to submit with permit()
|
||||
mapping(address => uint256) public _nonces;
|
||||
|
@ -45,7 +45,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
|
|||
}
|
||||
|
||||
constructor(
|
||||
LendingPool pool,
|
||||
ILendingPool pool,
|
||||
address underlyingAssetAddress,
|
||||
address reserveTreasuryAddress,
|
||||
string memory tokenName,
|
||||
|
|
|
@ -43,7 +43,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
|
|||
return 0;
|
||||
}
|
||||
|
||||
return scaledBalance.rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET));
|
||||
return scaledBalance.rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -102,7 +102,8 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
|
|||
* @return the total supply
|
||||
**/
|
||||
function totalSupply() public virtual override view returns (uint256) {
|
||||
return super.totalSupply().rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET));
|
||||
return
|
||||
super.totalSupply().rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,8 +15,8 @@ import {Errors} from '../../libraries/helpers/Errors.sol';
|
|||
*/
|
||||
|
||||
abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
|
||||
address internal immutable UNDERLYING_ASSET;
|
||||
ILendingPool internal immutable POOL;
|
||||
address public immutable UNDERLYING_ASSET_ADDRESS;
|
||||
ILendingPool public immutable POOL;
|
||||
mapping(address => uint256) internal _usersData;
|
||||
|
||||
/**
|
||||
|
@ -39,7 +39,7 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
|
|||
address incentivesController
|
||||
) public IncentivizedERC20(name, symbol, 18, incentivesController) {
|
||||
POOL = ILendingPool(pool);
|
||||
UNDERLYING_ASSET = underlyingAssetAddress;
|
||||
UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,10 +58,6 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
|
|||
_setDecimals(decimals);
|
||||
}
|
||||
|
||||
function underlyingAssetAddress() public view returns (address) {
|
||||
return UNDERLYING_ASSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Being non transferrable, the debt token does not implement any of the
|
||||
* standard ERC20 functions for transfer and allowance.
|
||||
|
|
13
contracts/tokenization/interfaces/ITokenConfiguration.sol
Normal file
13
contracts/tokenization/interfaces/ITokenConfiguration.sol
Normal file
|
@ -0,0 +1,13 @@
|
|||
pragma solidity ^0.6;
|
||||
|
||||
/**
|
||||
* @title ITokenConfiguration
|
||||
* @author Aave
|
||||
* @dev common interface between aTokens and debt tokens to fetch the
|
||||
* token configuration
|
||||
**/
|
||||
interface ITokenConfiguration {
|
||||
function UNDERLYING_ASSET_ADDRESS() external view returns (address);
|
||||
|
||||
function POOL() external view returns (address);
|
||||
}
|
|
@ -102,128 +102,6 @@ export const enableReservesAsCollateral = async (
|
|||
}
|
||||
};
|
||||
|
||||
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 def reserve');
|
||||
const rateStrategyContract = await deployDefaultReserveInterestRateStrategy(
|
||||
[
|
||||
lendingPoolAddressesProvider.address,
|
||||
baseVariableBorrowRate,
|
||||
variableRateSlope1,
|
||||
variableRateSlope2,
|
||||
stableRateSlope1,
|
||||
stableRateSlope2,
|
||||
],
|
||||
verify
|
||||
);
|
||||
|
||||
console.log('- Deploy stable deb totken ', assetSymbol);
|
||||
const stableDebtToken = await deployStableDebtToken(
|
||||
[
|
||||
lendingPool.address,
|
||||
tokenAddress,
|
||||
`Aave stable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
|
||||
`stableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
|
||||
incentivesController,
|
||||
],
|
||||
verify
|
||||
);
|
||||
|
||||
console.log('- Deploy var deb totken ', assetSymbol);
|
||||
const variableDebtToken = await deployVariableDebtToken(
|
||||
[
|
||||
lendingPool.address,
|
||||
tokenAddress,
|
||||
`Aave variable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
|
||||
`variableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
|
||||
incentivesController,
|
||||
],
|
||||
verify
|
||||
);
|
||||
|
||||
console.log('- Deploy a token ', 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('- init reserve currency ', assetSymbol);
|
||||
await waitForTx(
|
||||
await lendingPoolConfigurator.initReserve(
|
||||
tokenAddress,
|
||||
aToken.address,
|
||||
stableDebtToken.address,
|
||||
variableDebtToken.address,
|
||||
reserveDecimals,
|
||||
rateStrategyContract.address
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(`Reserve initialization for ${assetSymbol} failed with error ${e}. Skipped.`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const initReservesByHelper = async (
|
||||
lendingPoolProxy: tEthereumAddress,
|
||||
addressesProvider: tEthereumAddress,
|
||||
|
@ -339,7 +217,6 @@ export const initReservesByHelper = async (
|
|||
}
|
||||
|
||||
// Deploy init reserves per chunks
|
||||
const chunkedTokens = chunk(reserveTokens, initChunks);
|
||||
const chunkedStableTokens = chunk(deployedStableTokens, initChunks);
|
||||
const chunkedVariableTokens = chunk(deployedVariableTokens, initChunks);
|
||||
const chunkedAtokens = chunk(deployedATokens, initChunks);
|
||||
|
@ -347,11 +224,10 @@ export const initReservesByHelper = async (
|
|||
const chunkedDecimals = chunk(reserveInitDecimals, initChunks);
|
||||
const chunkedSymbols = chunk(Object.keys(tokenAddresses), initChunks);
|
||||
|
||||
console.log(`- Reserves initialization in ${chunkedTokens.length} txs`);
|
||||
console.log(`- Reserves initialization in ${chunkedStableTokens.length} txs`);
|
||||
for (let chunkIndex = 0; chunkIndex < chunkedDecimals.length; chunkIndex++) {
|
||||
const tx3 = await waitForTx(
|
||||
await atokenAndRatesDeployer.initReserve(
|
||||
chunkedTokens[chunkIndex],
|
||||
chunkedStableTokens[chunkIndex],
|
||||
chunkedVariableTokens[chunkIndex],
|
||||
chunkedAtokens[chunkIndex],
|
||||
|
@ -365,3 +241,149 @@ export const initReservesByHelper = async (
|
|||
// Set deployer back as admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(admin));
|
||||
};
|
||||
|
||||
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.`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -105,6 +105,7 @@ export enum ProtocolErrors {
|
|||
|
||||
//require error messages - LendingPoolAddressesProviderRegistry
|
||||
PROVIDER_NOT_REGISTERED = '37', // 'Provider is not registered'
|
||||
INVALID_ADDRESSES_PROVIDER_ID = '68',
|
||||
|
||||
//return error messages - LendingPoolCollateralManager
|
||||
HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '38', // 'Health factor is not below the threshold'
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
"@types/mocha": "7.0.2",
|
||||
"@types/node": "14.0.5",
|
||||
"bignumber.js": "9.0.0",
|
||||
"buidler-gas-reporter": "^0.1.3",
|
||||
"buidler-gas-reporter": "^0.1.4",
|
||||
"buidler-typechain": "0.1.1",
|
||||
"chai": "4.2.0",
|
||||
"chai-bignumber": "3.0.0",
|
||||
|
|
|
@ -20,6 +20,6 @@ task(
|
|||
|
||||
const addressesProviderRegistry = await deployLendingPoolAddressesProviderRegistry(verify);
|
||||
await waitForTx(
|
||||
await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 0)
|
||||
await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 1)
|
||||
);
|
||||
});
|
||||
|
|
|
@ -245,6 +245,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
};
|
||||
|
||||
before(async () => {
|
||||
console.log('aaaaa');
|
||||
await rawBRE.run('set-bre');
|
||||
const [deployer, secondaryWallet] = await getEthersSigners();
|
||||
console.log('-> Deploying test environment...');
|
||||
|
|
|
@ -17,6 +17,15 @@ makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => {
|
|||
);
|
||||
});
|
||||
|
||||
it('tries to register an addresses provider with id 0', async () => {
|
||||
const {users, registry} = testEnv;
|
||||
const {INVALID_ADDRESSES_PROVIDER_ID} = ProtocolErrors;
|
||||
|
||||
await expect(registry.registerAddressesProvider(users[2].address, '0')).to.be.revertedWith(
|
||||
INVALID_ADDRESSES_PROVIDER_ID
|
||||
);
|
||||
});
|
||||
|
||||
it('Registers a new mock addresses provider', async () => {
|
||||
const {users, registry} = testEnv;
|
||||
|
||||
|
|
|
@ -1,189 +0,0 @@
|
|||
import {makeSuite, TestEnv} from './helpers/make-suite';
|
||||
import {
|
||||
ProtocolErrors,
|
||||
TokenContractId,
|
||||
eContractid,
|
||||
AavePools,
|
||||
tEthereumAddress,
|
||||
} from '../helpers/types';
|
||||
import {getReservesConfigByPool} from '../helpers/configuration';
|
||||
import {
|
||||
deployAllMockTokens,
|
||||
deployLendingPoolAddressesProvider,
|
||||
deployLendingPoolAddressesProviderRegistry,
|
||||
deployLendingPool,
|
||||
deployLendingPoolConfigurator,
|
||||
deployPriceOracle,
|
||||
deployChainlinkProxyPriceProvider,
|
||||
deployLendingRateOracle,
|
||||
deployAaveProtocolTestHelpers,
|
||||
deployMockTokens,
|
||||
} from '../helpers/contracts-deployments';
|
||||
import {
|
||||
getFirstSigner,
|
||||
getLendingPool,
|
||||
getLendingPoolConfiguratorProxy,
|
||||
getPairsTokenAggregator,
|
||||
} from '../helpers/contracts-getters';
|
||||
import {insertContractAddressInDb} from '../helpers/contracts-helpers';
|
||||
import {waitForTx} from '../helpers/misc-utils';
|
||||
import {
|
||||
setInitialAssetPricesInOracle,
|
||||
deployAllMockAggregators,
|
||||
setInitialMarketRatesInRatesOracle,
|
||||
} from '../helpers/oracles-helpers';
|
||||
import AaveConfig from '../config/aave';
|
||||
import {initReservesByHelper} from '../helpers/init-helpers';
|
||||
import {ZERO_ADDRESS} from '../helpers/constants';
|
||||
|
||||
const MOCK_USD_PRICE_IN_WEI = AaveConfig.ProtocolGlobalParams.MockUsdPriceInWei;
|
||||
const ALL_ASSETS_INITIAL_PRICES = AaveConfig.Mocks.AllAssetsInitialPrices;
|
||||
const USD_ADDRESS = AaveConfig.ProtocolGlobalParams.UsdAddress;
|
||||
const MOCK_CHAINLINK_AGGREGATORS_PRICES = AaveConfig.Mocks.ChainlinkAggregatorPrices;
|
||||
const LENDING_RATE_ORACLE_RATES_COMMON = AaveConfig.LendingRateOracleRatesCommon;
|
||||
|
||||
makeSuite('Init helper test', (testEnv: TestEnv) => {
|
||||
it('Check init', async () => {
|
||||
const {deployer: deployerGuy} = testEnv;
|
||||
const deployer = deployerGuy.signer;
|
||||
|
||||
const aaveAdmin = await deployer.getAddress();
|
||||
|
||||
const mockTokens = await deployAllMockTokens();
|
||||
|
||||
const addressesProvider = await deployLendingPoolAddressesProvider();
|
||||
await waitForTx(await addressesProvider.setAaveAdmin(aaveAdmin));
|
||||
|
||||
const addressesProviderRegistry = await deployLendingPoolAddressesProviderRegistry();
|
||||
await waitForTx(
|
||||
await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 1)
|
||||
);
|
||||
|
||||
const lendingPoolImpl = await deployLendingPool();
|
||||
|
||||
await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address));
|
||||
|
||||
const address = await addressesProvider.getLendingPool();
|
||||
const lendingPoolProxy = await getLendingPool(address);
|
||||
|
||||
await insertContractAddressInDb(eContractid.LendingPool, lendingPoolProxy.address);
|
||||
|
||||
const lendingPoolConfiguratorImpl = await deployLendingPoolConfigurator();
|
||||
await waitForTx(
|
||||
await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImpl.address)
|
||||
);
|
||||
const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy(
|
||||
await addressesProvider.getLendingPoolConfigurator()
|
||||
);
|
||||
await insertContractAddressInDb(
|
||||
eContractid.LendingPoolConfigurator,
|
||||
lendingPoolConfiguratorProxy.address
|
||||
);
|
||||
|
||||
const fallbackOracle = await deployPriceOracle();
|
||||
await waitForTx(await fallbackOracle.setEthUsdPrice(MOCK_USD_PRICE_IN_WEI));
|
||||
await setInitialAssetPricesInOracle(
|
||||
ALL_ASSETS_INITIAL_PRICES,
|
||||
{
|
||||
WETH: mockTokens.WETH.address,
|
||||
DAI: mockTokens.DAI.address,
|
||||
TUSD: mockTokens.TUSD.address,
|
||||
USDC: mockTokens.USDC.address,
|
||||
USDT: mockTokens.USDT.address,
|
||||
SUSD: mockTokens.SUSD.address,
|
||||
LEND: mockTokens.LEND.address,
|
||||
BAT: mockTokens.BAT.address,
|
||||
REP: mockTokens.REP.address,
|
||||
MKR: mockTokens.MKR.address,
|
||||
LINK: mockTokens.LINK.address,
|
||||
KNC: mockTokens.KNC.address,
|
||||
WBTC: mockTokens.WBTC.address,
|
||||
MANA: mockTokens.MANA.address,
|
||||
ZRX: mockTokens.ZRX.address,
|
||||
SNX: mockTokens.SNX.address,
|
||||
BUSD: mockTokens.BUSD.address,
|
||||
|
||||
USD: USD_ADDRESS,
|
||||
|
||||
UNI_DAI_ETH: mockTokens.UNI_DAI_ETH.address,
|
||||
UNI_USDC_ETH: mockTokens.UNI_USDC_ETH.address,
|
||||
UNI_SETH_ETH: mockTokens.UNI_SETH_ETH.address,
|
||||
UNI_LEND_ETH: mockTokens.UNI_LEND_ETH.address,
|
||||
UNI_MKR_ETH: mockTokens.UNI_MKR_ETH.address,
|
||||
UNI_LINK_ETH: mockTokens.UNI_LINK_ETH.address,
|
||||
},
|
||||
fallbackOracle
|
||||
);
|
||||
|
||||
const mockAggregators = await deployAllMockAggregators(MOCK_CHAINLINK_AGGREGATORS_PRICES);
|
||||
|
||||
const allTokenAddresses = Object.entries(mockTokens).reduce(
|
||||
(accum: {[tokenSymbol: string]: tEthereumAddress}, [tokenSymbol, tokenContract]) => ({
|
||||
...accum,
|
||||
[tokenSymbol]: tokenContract.address,
|
||||
}),
|
||||
{}
|
||||
);
|
||||
const allAggregatorsAddresses = Object.entries(mockAggregators).reduce(
|
||||
(accum: {[tokenSymbol: string]: tEthereumAddress}, [tokenSymbol, aggregator]) => ({
|
||||
...accum,
|
||||
[tokenSymbol]: aggregator.address,
|
||||
}),
|
||||
{}
|
||||
);
|
||||
|
||||
const [tokens, aggregators] = getPairsTokenAggregator(
|
||||
allTokenAddresses,
|
||||
allAggregatorsAddresses
|
||||
);
|
||||
|
||||
const chainlinkProxyPriceProvider = await deployChainlinkProxyPriceProvider([
|
||||
tokens,
|
||||
aggregators,
|
||||
fallbackOracle.address,
|
||||
]);
|
||||
await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address));
|
||||
|
||||
const lendingRateOracle = await deployLendingRateOracle();
|
||||
await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address));
|
||||
|
||||
const {USD, ...tokensAddressesWithoutUsd} = allTokenAddresses;
|
||||
const allReservesAddresses = {
|
||||
...tokensAddressesWithoutUsd,
|
||||
};
|
||||
await setInitialMarketRatesInRatesOracle(
|
||||
LENDING_RATE_ORACLE_RATES_COMMON,
|
||||
allReservesAddresses,
|
||||
lendingRateOracle
|
||||
);
|
||||
|
||||
const {
|
||||
UNI_DAI_ETH,
|
||||
UNI_USDC_ETH,
|
||||
UNI_SETH_ETH,
|
||||
UNI_LINK_ETH,
|
||||
UNI_MKR_ETH,
|
||||
UNI_LEND_ETH,
|
||||
...protoPoolReservesAddresses
|
||||
} = <{[symbol: string]: tEthereumAddress}>allReservesAddresses;
|
||||
|
||||
const reservesParams = getReservesConfigByPool(AavePools.proto);
|
||||
|
||||
const testHelpers = await deployAaveProtocolTestHelpers(addressesProvider.address);
|
||||
|
||||
await insertContractAddressInDb(eContractid.AaveProtocolTestHelpers, testHelpers.address);
|
||||
|
||||
console.log('Initialize configuration');
|
||||
|
||||
await initReservesByHelper(
|
||||
lendingPoolProxy.address,
|
||||
addressesProvider.address,
|
||||
lendingPoolConfiguratorProxy.address,
|
||||
reservesParams,
|
||||
protoPoolReservesAddresses,
|
||||
testHelpers,
|
||||
await deployer.getAddress(),
|
||||
ZERO_ADDRESS
|
||||
);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user