Added missing stash work

This commit is contained in:
David Racero 2020-08-20 17:38:57 +02:00
parent 383f7fc3bb
commit 54d9e3a7ee
6 changed files with 269 additions and 210 deletions

View File

@ -1,3 +1,6 @@
import path from 'path';
import fs from 'fs';
import {usePlugin, BuidlerConfig} from '@nomiclabs/buidler/config';
// @ts-ignore
import {accounts} from './test-wallets.js';
@ -22,6 +25,13 @@ const MNEMONICS: {[network: string]: string} = {
[eEthereumNetwork.main]: '',
};
['misc', 'migrations', 'dev-deployment'].forEach((folder) => {
const tasksPath = path.join(__dirname, 'tasks', folder);
fs.readdirSync(tasksPath)
.filter((pth) => pth.includes('.ts'))
.forEach((task) => require(`${tasksPath}/${task}`));
});
const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number) => {
return {
url: `https://${networkName}.infura.io/v3/${INFURA_KEY}`,

View File

@ -9,6 +9,10 @@ import {
AavePools,
iParamsPerNetwork,
iParamsPerPool,
TokenContractId,
MockTokenMap,
iMultiPoolsAssets,
IReserveParams,
} from './types';
import {LendingPoolAddressesProvider} from '../types/LendingPoolAddressesProvider';
import {MintableErc20} from '../types/MintableErc20';
@ -33,6 +37,9 @@ 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 './constants';
import {verifyContract} from './etherscan-verification';
export const registerContractInJsonDb = async (contractId: string, contractInstance: Contract) => {
const currentNetwork = BRE.network.name;
@ -93,20 +100,47 @@ export const getContract = async <ContractType extends Contract>(
address: string
): Promise<ContractType> => (await BRE.ethers.getContractAt(contractName, address)) as ContractType;
export const deployLendingPoolAddressesProvider = async () =>
await deployContract<LendingPoolAddressesProvider>(eContractid.LendingPoolAddressesProvider, []);
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 () =>
await deployContract<LendingPoolAddressesProviderRegistry>(
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 deployFeeProvider = async () =>
await deployContract<FeeProvider>(eContractid.FeeProvider, []);
export const deployFeeProvider = async (verify?: boolean) => {
const instance = await deployContract<FeeProvider>(eContractid.FeeProvider, []);
export const deployLendingPoolConfigurator = async () =>
await deployContract<LendingPoolConfigurator>(eContractid.LendingPoolConfigurator, []);
if (verify) {
await verifyContract(eContractid.FeeProvider, 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);
@ -162,20 +196,27 @@ export const linkLibrariesToArtifact = async (artifact: Artifact) => {
return factory;
};
export const deployLendingPool = async () => {
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();
return (await lendingPool.deployed()) as LendingPool;
const instance = (await lendingPool.deployed()) as LendingPool;
if (verify) {
await verifyContract(eContractid.LendingPool, instance.address, []);
}
return instance;
};
export const deployPriceOracle = async () =>
await deployContract<PriceOracle>(eContractid.PriceOracle, []);
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 deployMockAggregator = async (price: tStringTokenSmallUnits) =>
await deployContract<MockAggregator>(eContractid.MockAggregator, [price]);
@ -482,3 +523,179 @@ export const convertToCurrencyUnits = async (tokenAddress: string, amount: strin
const amountInCurrencyUnits = new BigNumber(amount).div(currencyUnit);
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 getMockedTokens = 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, ...assetsAddressesWithoutEth} = allAssetsAddresses;
const pairs = Object.entries(assetsAddressesWithoutEth).map(([tokenSymbol, tokenAddress]) => {
if (tokenSymbol !== 'ETH') {
const aggregatorAddressIndex = Object.keys(aggregatorsAddresses).findIndex(
(value) => value === tokenSymbol
);
const [, aggregatorAddress] = (Object.entries(aggregatorsAddresses) as [
string,
tEthereumAddress
][])[aggregatorAddressIndex];
return [tokenAddress, aggregatorAddress];
}
});
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,
lendingPoolConfigurator: LendingPoolConfigurator,
aavePool: AavePools
) => {
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 lendingPool.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];
const rateStrategyContract = await deployDefaultReserveInterestRateStrategy([
lendingPoolAddressesProvider.address,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,
stableRateSlope1,
stableRateSlope2,
]);
const stableDebtToken = await deployStableDebtToken([
`Aave stable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
`stableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
tokenAddress,
lendingPool.address,
]);
const variableDebtToken = await deployVariableDebtToken([
`Aave variable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
`variableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
tokenAddress,
lendingPool.address,
]);
const aToken = await deployGenericAToken([
lendingPool.address,
tokenAddress,
`Aave interest bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
`a${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
]);
if (process.env.POOL === AavePools.secondary) {
if (assetSymbol.search('UNI') === -1) {
assetSymbol = `Uni${assetSymbol}`;
} else {
assetSymbol = assetSymbol.replace(/_/g, '').replace('UNI', 'Uni');
}
}
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.`);
}
}
};

View File

@ -3,7 +3,7 @@ import BN = require('bn.js');
import low from 'lowdb';
import FileSync from 'lowdb/adapters/FileSync';
import {WAD} from './constants';
import {Wallet} from 'ethers';
import {Wallet, ContractTransaction} from 'ethers';
import {BuidlerRuntimeEnvironment} from '@nomiclabs/buidler/types';
export const toWad = (value: string | number) => new BigNumber(value).times(WAD).toFixed();
@ -40,3 +40,5 @@ export const increaseTime = async (secondsToIncrease: number) => {
await BRE.ethers.provider.send('evm_increaseTime', [secondsToIncrease]);
await BRE.ethers.provider.send('evm_mine', []);
};
export const waitForTx = async (tx: ContractTransaction) => await tx.wait();

View File

@ -1,4 +1,6 @@
import BigNumber from 'bignumber.js';
import {MockContract} from 'ethereum-waffle';
import {MintableErc20} from '../types/MintableErc20';
export enum eEthereumNetwork {
buidlerevm = 'buidlerevm',
@ -224,3 +226,9 @@ export enum RateMode {
Stable = '1',
Variable = '2',
}
export interface ObjectString {
[key: string]: string;
}
export type MockTokenMap = {[symbol: string]: MockContract | MintableErc20};

View File

@ -13,10 +13,15 @@
"types-gen": "typechain --target ethers-v5 --outDir ./types './artifacts/*.json'",
"test": "buidler test",
"test-scenarios": "buidler test test/__setup.spec.ts test/scenario.spec.ts",
"dev:coverage": "buidler coverage",
"dev:deployment": "buidler dev-deployment",
"dev:deployExample": "buidler deploy-Example",
"dev:prettier": "prettier --write ."
"coverage": "buidler coverage",
"evm:dev:migration": "buidler dev-migration",
"evm:full:migration": "buidler full-migration",
"kovan:dev:migration": "npm run buidler-kovan -- dev-migration --verify",
"kovan:full:migration": "npm run buidler-kovan -- full-migration --verify",
"ropsten:dev:migration": "npm run buidler-ropsten -- dev-migration --verify",
"ropsten:full:migration": "npm run buidler-ropsten -- full-migration --verify",
"main:dev:migration": "npm run buidler-main -- dev-migration --verify",
"main:full:migration": "npm run buidler-main -- full-migration --verify"
},
"devDependencies": {
"@nomiclabs/buidler": "1.4.4",

View File

@ -9,7 +9,6 @@ import {
deployLendingPool,
deployPriceOracle,
getLendingPoolConfiguratorProxy,
deployMockAggregator,
deployChainlinkProxyPriceProvider,
deployLendingRateOracle,
deployDefaultReserveInterestRateStrategy,
@ -27,16 +26,14 @@ import {
deployStableDebtToken,
deployVariableDebtToken,
deployGenericAToken,
getPairsTokenAggregator,
} from '../helpers/contracts-helpers';
import {LendingPoolAddressesProvider} from '../types/LendingPoolAddressesProvider';
import {Wallet, ContractTransaction, ethers, Signer} from 'ethers';
import {Signer} from 'ethers';
import {
TokenContractId,
eContractid,
iAssetBase,
tEthereumAddress,
iAssetAggregatorBase,
IMarketRates,
iMultiPoolsAssets,
AavePools,
IReserveParams,
@ -52,19 +49,16 @@ import {
getFeeDistributionParamsCommon,
ZERO_ADDRESS,
} from '../helpers/constants';
import {PriceOracle} from '../types/PriceOracle';
import {MockAggregator} from '../types/MockAggregator';
import {LendingRateOracle} from '../types/LendingRateOracle';
import {LendingPool} from '../types/LendingPool';
import {LendingPoolConfigurator} from '../types/LendingPoolConfigurator';
import {initializeMakeSuite} from './helpers/make-suite';
import path from 'path';
import fs from 'fs';
['misc'].forEach((folder) => {
const tasksPath = path.join('/src/', 'tasks', folder);
fs.readdirSync(tasksPath).forEach((task) => require(`${tasksPath}/${task}`));
});
import {
setInitialAssetPricesInOracle,
setInitialMarketRatesInRatesOracle,
deployAllMockAggregators,
} from '../helpers/oracles-helpers';
import {waitForTx} from '../helpers/misc-utils';
const deployAllMockTokens = async (deployer: Signer) => {
const tokens: {[symbol: string]: MockContract | MintableErc20} = {};
@ -96,181 +90,6 @@ const deployAllMockTokens = async (deployer: Signer) => {
return tokens;
};
const setInitialAssetPricesInOracle = async (
prices: iAssetBase<tEthereumAddress>,
assetsAddresses: iAssetBase<tEthereumAddress>,
priceOracleInstance: PriceOracle
) => {
for (const [assetSymbol, price] of Object.entries(prices) as [string, string][]) {
const assetAddressIndex = Object.keys(assetsAddresses).findIndex(
(value) => value === assetSymbol
);
const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[
assetAddressIndex
];
await waitForTx(await priceOracleInstance.setAssetPrice(assetAddress, price));
}
};
const deployAllMockAggregators = async (initialPrices: iAssetAggregatorBase<string>) => {
const aggregators: {[tokenSymbol: string]: MockAggregator} = {};
for (const tokenContractName of Object.keys(initialPrices)) {
if (tokenContractName !== 'ETH') {
const priceIndex = Object.keys(initialPrices).findIndex(
(value) => value === tokenContractName
);
const [, price] = (Object.entries(initialPrices) as [string, string][])[priceIndex];
aggregators[tokenContractName] = await deployMockAggregator(price);
}
}
return aggregators;
};
const getPairsTokenAggregator = (
allAssetsAddresses: {
[tokenSymbol: string]: tEthereumAddress;
},
aggregatorsAddresses: {[tokenSymbol: string]: tEthereumAddress}
): [string[], string[]] => {
const {ETH, ...assetsAddressesWithoutEth} = allAssetsAddresses;
const pairs = Object.entries(assetsAddressesWithoutEth).map(([tokenSymbol, tokenAddress]) => {
if (tokenSymbol !== 'ETH') {
const aggregatorAddressIndex = Object.keys(aggregatorsAddresses).findIndex(
(value) => value === tokenSymbol
);
const [, aggregatorAddress] = (Object.entries(aggregatorsAddresses) as [
string,
tEthereumAddress
][])[aggregatorAddressIndex];
return [tokenAddress, aggregatorAddress];
}
});
const mappedPairs = pairs.map(([asset]) => asset);
const mappedAggregators = pairs.map(([, source]) => source);
return [mappedPairs, mappedAggregators];
};
const setInitialMarketRatesInRatesOracle = async (
marketRates: iMultiPoolsAssets<IMarketRates>,
assetsAddresses: {[x: string]: tEthereumAddress},
lendingRateOracleInstance: LendingRateOracle
) => {
for (const [assetSymbol, {borrowRate}] of Object.entries(marketRates) as [
string,
IMarketRates
][]) {
const assetAddressIndex = Object.keys(assetsAddresses).findIndex(
(value) => value === assetSymbol
);
const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[
assetAddressIndex
];
await lendingRateOracleInstance.setMarketBorrowRate(assetAddress, borrowRate);
}
};
const initReserves = async (
reservesParams: iMultiPoolsAssets<IReserveParams>,
tokenAddresses: {[symbol: string]: tEthereumAddress},
lendingPoolAddressesProvider: LendingPoolAddressesProvider,
lendingPool: LendingPool,
lendingPoolConfigurator: LendingPoolConfigurator,
aavePool: AavePools
) => {
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 lendingPool.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];
const rateStrategyContract = await deployDefaultReserveInterestRateStrategy([
lendingPoolAddressesProvider.address,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,
stableRateSlope1,
stableRateSlope2,
]);
const stableDebtToken = await deployStableDebtToken([
`Aave stable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
`stableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
tokenAddress,
lendingPool.address,
]);
const variableDebtToken = await deployVariableDebtToken([
`Aave variable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
`variableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
tokenAddress,
lendingPool.address,
]);
const aToken = await deployGenericAToken([
lendingPool.address,
tokenAddress,
`Aave interest bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
`a${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`,
]);
if (process.env.POOL === AavePools.secondary) {
if (assetSymbol.search('UNI') === -1) {
assetSymbol = `Uni${assetSymbol}`;
} else {
assetSymbol = assetSymbol.replace(/_/g, '').replace('UNI', 'Uni');
}
}
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.`);
}
}
};
const enableReservesToBorrow = async (
reservesParams: iMultiPoolsAssets<IReserveParams>,
tokenAddresses: {[symbol: string]: tEthereumAddress},
@ -348,8 +167,6 @@ const enableReservesAsCollateral = async (
}
};
export const waitForTx = async (tx: ContractTransaction) => await tx.wait();
const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
console.time('setup');
const lendingPoolManager = await deployer.getAddress();