WIP: Added dev-deployment scripts. Moved some helpers and mocks outside of test setup.

This commit is contained in:
David Racero 2020-08-20 17:35:05 +02:00
parent 7d23041849
commit 383f7fc3bb
9 changed files with 528 additions and 0 deletions

View File

@ -0,0 +1,96 @@
import {BRE} from './misc-utils';
export const SUPPORTED_ETHERSCAN_NETWORKS = ['main', 'ropsten', 'kovan'];
export const getEtherscanPath = async (contractName: string) => {
const compilerInput = await BRE.run('compile:get-compiler-input');
const paths = Object.keys(compilerInput.sources);
const path = paths.find((p) => p.includes(contractName));
if (!path) {
throw new Error(
`Contract path not found for ${contractName}. Check if smart contract file is equal to contractName input.`
);
}
return `${path}:${contractName}`;
};
function delay(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export const verifyContract = async (
contractName: string,
address: string,
constructorArguments: string[],
libraries?: string
) => {
const currentNetwork = BRE.network.name;
if (!process.env.ETHERSCAN_KEY) {
throw Error('Missing process.env.ETHERSCAN_KEY.');
}
if (!process.env.ETHERSCAN_NETWORK) {
throw Error('Missing process.env.ETHERSCAN_NETWORK');
}
if (!SUPPORTED_ETHERSCAN_NETWORKS.includes(currentNetwork)) {
throw Error(
`Current network ${currentNetwork} not supported. Please change to one of the next networks: ${SUPPORTED_ETHERSCAN_NETWORKS.toString()}`
);
}
const etherscanPath = await getEtherscanPath(contractName);
const params = {
contractName: etherscanPath,
address: address,
constructorArguments,
libraries,
};
try {
console.log(
'[ETHERSCAN][WARNING] Delaying Etherscan verification due their API can not find newly deployed contracts'
);
const msDelay = 3000;
const times = 30;
await runTaskWithRetry('verify-contract', params, times, msDelay);
} catch (error) {}
};
export const runTaskWithRetry = async (
task: string,
params: any,
times: number,
msDelay: number
) => {
let counter = times;
await delay(msDelay);
try {
if (times) {
await BRE.run(task, params);
} else {
console.error('[ERROR] Errors after all the retries, check the logs for more information.');
}
} catch (error) {
counter--;
console.info(`[INFO] Retrying attemps: ${counter}.`);
console.error('[ERROR]', error.message);
await runTaskWithRetry(task, params, counter, msDelay);
}
};
export const checkVerification = () => {
const currentNetwork = BRE.network.name;
if (!process.env.ETHERSCAN_KEY) {
throw Error('Missing process.env.ETHERSCAN_KEY.');
}
if (!process.env.ETHERSCAN_NETWORK) {
throw Error('Missing process.env.ETHERSCAN_NETWORK');
}
if (!SUPPORTED_ETHERSCAN_NETWORKS.includes(currentNetwork)) {
throw Error(
`Current network ${currentNetwork} not supported. Please change to one of the next networks: ${SUPPORTED_ETHERSCAN_NETWORKS.toString()}`
);
}
};

View File

@ -0,0 +1,62 @@
import {
tEthereumAddress,
iMultiPoolsAssets,
IMarketRates,
iAssetBase,
iAssetAggregatorBase,
} from './types';
import {LendingRateOracle} from '../types/LendingRateOracle';
import {PriceOracle} from '../types/PriceOracle';
import {MockAggregator} from '../types/MockAggregator';
import {deployMockAggregator} from './contracts-helpers';
import {waitForTx} from './misc-utils';
export 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);
}
};
export 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));
}
};
export 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;
};

View File

@ -0,0 +1,9 @@
import {task} from '@nomiclabs/buidler/config';
import {deployAllMockTokens} from '../../helpers/contracts-helpers';
task('deploy-mock-tokens', 'Deploy mock tokens for dev enviroment')
.addOptionalParam('verify', 'Verify contracts at Etherscan')
.setAction(async ({verify}, localBRE) => {
await localBRE.run('set-bre');
await deployAllMockTokens(verify);
});

View File

@ -0,0 +1,35 @@
import {task} from '@nomiclabs/buidler/config';
import {
deployLendingPoolAddressesProvider,
deployLendingPoolAddressesProviderRegistry,
deployFeeProvider,
getFeeProvider,
insertContractAddressInDb,
} from '../../helpers/contracts-helpers';
import {eContractid} from '../../helpers/types';
import {waitForTx} from '../../helpers/misc-utils';
task(
'deploy-address-provider',
'Deploy address provider, registry and fee provider for dev enviroment'
)
.addOptionalParam('verify', 'Verify contracts at Etherscan')
.setAction(async ({verify}, localBRE) => {
await localBRE.run('set-bre');
const lendingPoolManager = await (await localBRE.ethers.getSigners())[0].getAddress();
const addressesProvider = await deployLendingPoolAddressesProvider(verify);
await waitForTx(await addressesProvider.setLendingPoolManager(lendingPoolManager));
const addressesProviderRegistry = await deployLendingPoolAddressesProviderRegistry(verify);
await waitForTx(
await addressesProviderRegistry.registerAddressesProvider(addressesProvider.address, 0)
);
const feeProviderImpl = await deployFeeProvider(verify);
await waitForTx(await addressesProvider.setFeeProviderImpl(feeProviderImpl.address));
const feeProviderProxy = await getFeeProvider(await addressesProvider.getFeeProvider());
await insertContractAddressInDb(eContractid.FeeProvider, feeProviderProxy.address);
});

View File

@ -0,0 +1,44 @@
import {task} from '@nomiclabs/buidler/config';
import {
deployLendingPool,
getLendingPoolAddressesProvider,
getLendingPool,
insertContractAddressInDb,
deployLendingPoolConfigurator,
getLendingPoolConfiguratorProxy,
} from '../../helpers/contracts-helpers';
import {eContractid} from '../../helpers/types';
import {waitForTx} from '../../helpers/misc-utils';
task('deploy-lending-pool', 'Deploy lending pool for dev enviroment')
.addOptionalParam('verify', 'Verify contracts at Etherscan')
.setAction(async ({verify}, localBRE) => {
await localBRE.run('set-bre');
const addressesProvider = await getLendingPoolAddressesProvider();
const lendingPoolImpl = await deployLendingPool(verify);
// Set lending pool impl to Address Provider
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(verify);
// Set lending pool conf impl to Address Provider
await waitForTx(
await addressesProvider.setLendingPoolConfiguratorImpl(lendingPoolConfiguratorImpl.address)
);
const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy(
await addressesProvider.getLendingPoolConfigurator()
);
await insertContractAddressInDb(
eContractid.LendingPoolConfigurator,
lendingPoolConfiguratorProxy.address
);
});

View File

@ -0,0 +1,111 @@
import {task} from '@nomiclabs/buidler/config';
import {
getLendingPoolAddressesProvider,
deployPriceOracle,
getMockedTokens,
getPairsTokenAggregator,
deployChainlinkProxyPriceProvider,
deployLendingRateOracle,
} from '../../helpers/contracts-helpers';
import {
MOCK_USD_PRICE_IN_WEI,
ALL_ASSETS_INITIAL_PRICES,
USD_ADDRESS,
MOCK_CHAINLINK_AGGREGATORS_PRICES,
LENDING_RATE_ORACLE_RATES_COMMON,
} from '../../helpers/constants';
import {
setInitialAssetPricesInOracle,
deployAllMockAggregators,
setInitialMarketRatesInRatesOracle,
} from '../../helpers/oracles-helpers';
import {tEthereumAddress} from '../../helpers/types';
import {waitForTx} from '../../helpers/misc-utils';
task('deploy-oracles', 'Deploy oracles for dev enviroment')
.addOptionalParam('verify', 'Verify contracts at Etherscan')
.setAction(async ({verify}, localBRE) => {
await localBRE.run('set-bre');
const mockTokens = await getMockedTokens();
const addressesProvider = await getLendingPoolAddressesProvider();
const fallbackOracle = await deployPriceOracle(verify);
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
);
// TODO: Missing verify
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
);
// TODO: Missing verify and getter
const chainlinkProxyPriceProvider = await deployChainlinkProxyPriceProvider([
tokens,
aggregators,
fallbackOracle.address,
]);
await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address));
// TODO: Missing verify
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
);
});

View File

@ -0,0 +1,102 @@
import {task} from '@nomiclabs/buidler/config';
import {
getLendingPoolAddressesProvider,
getMockedTokens,
initReserves,
} from '../../helpers/contracts-helpers';
import {getReservesConfigByPool} from '../../helpers/constants';
import {tEthereumAddress, AavePools} from '../../helpers/types';
import {waitForTx} from '../../helpers/misc-utils';
task('initialize-lending-pool', 'Deploy oracles for dev enviroment')
.addOptionalParam('verify', 'Verify contracts at Etherscan')
.setAction(async ({verify}, localBRE) => {
await localBRE.run('set-bre');
const mockTokens = await getMockedTokens();
const allTokenAddresses = Object.entries(mockTokens).reduce(
(accum: {[tokenSymbol: string]: tEthereumAddress}, [tokenSymbol, tokenContract]) => ({
...accum,
[tokenSymbol]: tokenContract.address,
}),
{}
);
const addressesProvider = await getLendingPoolAddressesProvider();
const {
UNI_DAI_ETH,
UNI_USDC_ETH,
UNI_SETH_ETH,
UNI_LINK_ETH,
UNI_MKR_ETH,
UNI_LEND_ETH,
...protoPoolReservesAddresses
} = <{[symbol: string]: tEthereumAddress}>allTokenAddresses;
const reservesParams = getReservesConfigByPool(AavePools.proto);
console.log('Initialize configuration');
await initReserves(
reservesParams,
protoPoolReservesAddresses,
addressesProvider,
lendingPoolProxy,
lendingPoolConfiguratorProxy,
AavePools.proto
);
await enableReservesToBorrow(
reservesParams,
protoPoolReservesAddresses,
lendingPoolProxy,
lendingPoolConfiguratorProxy
);
await enableReservesAsCollateral(
reservesParams,
protoPoolReservesAddresses,
lendingPoolProxy,
lendingPoolConfiguratorProxy
);
const liquidationManager = await deployLendingPoolLiquidationManager();
await waitForTx(
await addressesProvider.setLendingPoolLiquidationManager(liquidationManager.address)
);
const {receivers, percentages} = getFeeDistributionParamsCommon(lendingPoolManager);
const tokenDistributorImpl = await deployTokenDistributor();
const tokenDistributorProxy = await deployInitializableAdminUpgradeabilityProxy();
const implementationParams = tokenDistributorImpl.interface.encodeFunctionData('initialize', [
ZERO_ADDRESS,
tokensAddressesWithoutUsd.LEND,
'0x0000000000000000000000000000000000000000', // TODO: finish removal
receivers,
percentages,
Object.values(tokensAddressesWithoutUsd),
]);
await waitForTx(
await tokenDistributorProxy['initialize(address,address,bytes)'](
tokenDistributorImpl.address,
await secondaryWallet.getAddress(),
implementationParams
)
);
await waitForTx(await addressesProvider.setTokenDistributor(tokenDistributorProxy.address));
await insertContractAddressInDb(eContractid.TokenDistributor, tokenDistributorProxy.address);
const mockFlashLoanReceiver = await deployMockFlashLoanReceiver(addressesProvider.address);
await insertContractAddressInDb(
eContractid.MockFlashLoanReceiver,
mockFlashLoanReceiver.address
);
await deployWalletBalancerProvider(addressesProvider.address);
const testHelpers = await deployAaveProtocolTestHelpers(addressesProvider.address);
await insertContractAddressInDb(eContractid.AaveProtocolTestHelpers, testHelpers.address);
});

View File

@ -0,0 +1,34 @@
import {task} from '@nomiclabs/buidler/config';
import {checkVerification} from '../../helpers/etherscan-verification';
task('dev-migration', 'Deploy development enviroment')
.addOptionalParam('verify', 'Verify contracts at Etherscan')
.setAction(async ({verify}, localBRE) => {
await localBRE.run('set-bre');
// Prevent loss of gas verifying all the needed ENVs for Etherscan verification
if (verify) {
checkVerification();
}
console.log('Migration started\n');
console.log('1. Deploy mock tokens');
await localBRE.run('deploy-mock-tokens');
console.log('2. Deploy address provider');
await localBRE.run('deploy-address-provider');
console.log('3. Deploy lending pool');
await localBRE.run('deploy-lending-pool');
console.log('4. Deploy oracles');
await localBRE.run('deploy-oracles');
// 5. Initialize lending pool configuration
//
// console.log('5. Initialize lending pool')
// await localBRE.run('initialize-lending-pool');
console.log('\nFinished migration');
});

35
tasks/misc/verify-sc.ts Normal file
View File

@ -0,0 +1,35 @@
import {task} from '@nomiclabs/buidler/config';
import {verifyContract, checkVerification} from '../../helpers/etherscan-verification';
interface VerifyParams {
contractName: string;
address: string;
constructorArguments: string[];
libraries: string;
}
task('verify-sc', 'Inits the BRE, to have access to all the plugins')
.addParam('contractName', 'Name of the Solidity smart contract')
.addParam('address', 'Ethereum address of the smart contract')
.addOptionalParam(
'libraries',
'Stringified JSON object in format of {library1: "0x2956356cd2a2bf3202f771f50d3d14a367b48071"}'
)
.addOptionalVariadicPositionalParam(
'constructorArguments',
'arguments for contract constructor',
[]
)
.setAction(
async (
{contractName, address, constructorArguments = [], libraries}: VerifyParams,
localBRE
) => {
await localBRE.run('set-bre');
checkVerification();
const result = await verifyContract(contractName, address, constructorArguments, libraries);
return result;
}
);