diff --git a/hardhat.config.ts b/hardhat.config.ts index fafa0eff..df732515 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,10 +1,10 @@ import path from 'path'; import fs from 'fs'; -import {HardhatUserConfig} from 'hardhat/types'; +import { HardhatUserConfig } from 'hardhat/types'; // @ts-ignore -import {accounts} from './test-wallets.js'; -import {eEthereumNetwork} from './helpers/types'; -import {BUIDLEREVM_CHAINID, COVERAGE_CHAINID} from './helpers/buidler-constants'; +import { accounts } from './test-wallets.js'; +import { eEthereumNetwork } from './helpers/types'; +import { BUIDLEREVM_CHAINID, COVERAGE_CHAINID } from './helpers/buidler-constants'; import '@nomiclabs/hardhat-ethers'; import '@nomiclabs/hardhat-waffle'; @@ -62,7 +62,7 @@ const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number const mainnetFork = MAINNET_FORK ? { - blockNumber: 11268220, + blockNumber: 11361132, url: ALCHEMY_KEY ? `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}` : `https://main.infura.io/v3/${INFURA_KEY}`, @@ -73,7 +73,7 @@ const buidlerConfig: HardhatUserConfig = { solidity: { version: '0.6.12', settings: { - optimizer: {enabled: true, runs: 200}, + optimizer: { enabled: true, runs: 200 }, evmVersion: 'istanbul', }, }, @@ -109,7 +109,7 @@ const buidlerConfig: HardhatUserConfig = { chainId: BUIDLEREVM_CHAINID, throwOnTransactionFailures: true, throwOnCallFailures: true, - accounts: accounts.map(({secretKey, balance}: {secretKey: string; balance: string}) => ({ + accounts: accounts.map(({ secretKey, balance }: { secretKey: string; balance: string }) => ({ privateKey: secretKey, balance, })), diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index f1ea4e6b..668124f0 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -7,7 +7,7 @@ import { getStableAndVariableTokensHelper, } from './contracts-getters'; import { rawInsertContractAddressInDb } from './contracts-helpers'; -import { BigNumberish } from 'ethers'; +import { BigNumber, BigNumberish } from 'ethers'; import { deployDefaultReserveInterestRateStrategy, deployDelegationAwareAToken, @@ -35,8 +35,8 @@ export const initReservesByHelper = async ( treasuryAddress: tEthereumAddress, incentivesController: tEthereumAddress, verify: boolean -) => { - +): Promise => { + let gasUsage = BigNumber.from('0'); const stableAndVariableDeployer = await getStableAndVariableTokensHelper(); const atokenAndRatesDeployer = await getATokensAndRatesHelper(); @@ -47,8 +47,8 @@ export const initReservesByHelper = async ( await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address)); // CHUNK CONFIGURATION - const tokensChunks = 4; - const initChunks = 6; + const tokensChunks = 2; + const initChunks = 4; // Deploy tokens and rates that uses common aToken in chunks const reservesChunks = chunk( @@ -123,17 +123,13 @@ export const initReservesByHelper = async ( // Deploy stable and variable deployers and save implementations const tx1 = await waitForTx( - await stableAndVariableDeployer.initDeployment( - tokens, - symbols, - incentivesController - ) + await stableAndVariableDeployer.initDeployment(tokens, symbols, incentivesController) ); tx1.events?.forEach((event, index) => { rawInsertContractAddressInDb(`stableDebt${symbols[index]}`, event?.args?.stableToken); rawInsertContractAddressInDb(`variableDebt${symbols[index]}`, event?.args?.variableToken); }); - + // Deploy atokens and rate strategies and save implementations const tx2 = await waitForTx( await atokenAndRatesDeployer.initDeployment( @@ -150,6 +146,10 @@ export const initReservesByHelper = async ( }); console.log(` - Deployed aToken, DebtTokens and Strategy for: ${symbols.join(', ')} `); + console.log(' * gasUsed: debtTokens batch', tx1.gasUsed.toString()); + console.log(' * gasUsed: aTokens and Strategy batch', tx2.gasUsed.toString()); + gasUsage = gasUsage.add(tx1.gasUsed).add(tx2.gasUsed); + 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) || []; @@ -252,11 +252,15 @@ export const initReservesByHelper = async ( chunkedDecimals[chunkIndex] ) ); + console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`); + console.log(' * gasUsed', tx3.gasUsed.toString()); + gasUsage = gasUsage.add(tx3.gasUsed); } // Set deployer back as admin await waitForTx(await addressProvider.setPoolAdmin(admin)); + return gasUsage; }; export const getPairsTokenAggregator = ( @@ -304,7 +308,13 @@ export const configureReservesByHelper = async ( for (const [ assetSymbol, - { baseLTVAsCollateral, liquidationBonus, liquidationThreshold, reserveFactor, stableBorrowRateEnabled }, + { + baseLTVAsCollateral, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + }, ] of Object.entries(reservesParams) as [string, IReserveParams][]) { if (baseLTVAsCollateral === '-1') continue; diff --git a/helpers/types.ts b/helpers/types.ts index c59270c3..35211dd1 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -351,6 +351,7 @@ export interface ICommonConfiguration { ProtocolGlobalParams: IProtocolGlobalConfig; Mocks: IMocksConfig; ProviderRegistry: iParamsPerNetwork; + ProviderRegistryOwner: iParamsPerNetwork; LendingRateOracleRatesCommon: iMultiPoolsAssets; LendingRateOracle: iParamsPerNetwork; TokenDistributor: iParamsPerNetwork; diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index 2bb304d8..f2fdb6f3 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -137,13 +137,22 @@ export const CommonsConfig: ICommonConfiguration = { }, EmergencyAdminIndex: 1, ProviderRegistry: { - [eEthereumNetwork.kovan]: '', + [eEthereumNetwork.kovan]: '0x1E40B561EC587036f9789aF83236f057D1ed2A90', [eEthereumNetwork.ropsten]: '', - [eEthereumNetwork.main]: '', + [eEthereumNetwork.main]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.tenderlyMain]: '', + [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', + }, + ProviderRegistryOwner: { + [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', + [eEthereumNetwork.ropsten]: '', + [eEthereumNetwork.main]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', + [eEthereumNetwork.coverage]: '', + [eEthereumNetwork.hardhat]: '', + [eEthereumNetwork.buidlerevm]: '', + [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', }, LendingRateOracle: { [eEthereumNetwork.coverage]: '', @@ -307,7 +316,7 @@ export const CommonsConfig: ICommonConfiguration = { }, ReserveFactorTreasuryAddress: { [eEthereumNetwork.coverage]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', - [eEthereumNetwork.hardhat]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + [eEthereumNetwork.hardhat]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.buidlerevm]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.kovan]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.ropsten]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', diff --git a/package.json b/package.json index 14dd43c3..3de43f31 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "aave:ropsten:full:migration": "npm run compile && npm run hardhat:ropsten -- aave:mainnet --verify", "aave:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- aave:mainnet", "aave:fork:main": "npm run compile && MAINNET_FORK=true hardhat aave:mainnet", - "aave:main:full:migration": "npm run hardhat:main -- aave:mainnet --verify", + "aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify", "dev:prettier": "prettier --write .", "ci:test": "npm run compile && npm run test", "ci:clean": "rm -rf ./artifacts ./cache ./types", @@ -48,7 +48,8 @@ "mainnet:verify": "npm run hardhat:main verify:general -- --all --pool Aave", "kovan:verify:tokens": "npm run hardhat:kovan verify:tokens -- --pool Aave", "ropsten:verify:tokens": "npm run hardhat:ropsten verify:tokens -- --pool Aave", - "mainnet:verify:tokens": "npm run hardhat:main verify:tokens -- --pool Aave" + "mainnet:verify:tokens": "npm run hardhat:main verify:tokens -- --pool Aave", + "print-config:fork:mainnet": "MAINNET_FORK=true hardhat print-config:fork" }, "devDependencies": { "@nomiclabs/buidler": "^1.4.7", diff --git a/tasks/full/0_address_provider_registry.ts b/tasks/full/0_address_provider_registry.ts new file mode 100644 index 00000000..19b5e1f2 --- /dev/null +++ b/tasks/full/0_address_provider_registry.ts @@ -0,0 +1,11 @@ +import { task } from 'hardhat/config'; +import { deployLendingPoolAddressesProviderRegistry } from '../../helpers/contracts-deployments'; + +task('full:deploy-address-provider-registry', 'Deploy address provider registry') + .addFlag('verify', 'Verify contracts at Etherscan') + .setAction(async ({ verify }, DRE) => { + await DRE.run('set-DRE'); + + const contract = await deployLendingPoolAddressesProviderRegistry(verify); + console.log('Registry Address:', contract.address); + }); diff --git a/tasks/full/1_address_provider.ts b/tasks/full/1_address_provider.ts index ea196f57..29b90af3 100644 --- a/tasks/full/1_address_provider.ts +++ b/tasks/full/1_address_provider.ts @@ -12,7 +12,13 @@ import { getEmergencyAdmin, } from '../../helpers/configuration'; import { eEthereumNetwork } from '../../helpers/types'; -import { getLendingPoolAddressesProviderRegistry } from '../../helpers/contracts-getters'; +import { + getFirstSigner, + getLendingPoolAddressesProviderRegistry, +} from '../../helpers/contracts-getters'; +import { isAddress } from 'ethers/lib/utils'; +import { isZeroAddress } from 'ethereumjs-util'; +import { Signer } from 'ethers'; task( 'full:deploy-address-provider', @@ -22,30 +28,70 @@ task( .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ verify, pool }, DRE) => { await DRE.run('set-DRE'); - + let signer: Signer; const network = DRE.network.name; const poolConfig = loadPoolConfig(pool); const { ProviderId, MarketId } = poolConfig; const providerRegistryAddress = getParamPerNetwork(poolConfig.ProviderRegistry, network); - // Deploy address provider and set genesis manager + const providerRegistryOwner = getParamPerNetwork(poolConfig.ProviderRegistryOwner, network); + + if ( + !providerRegistryAddress || + !isAddress(providerRegistryAddress) || + isZeroAddress(providerRegistryAddress) + ) { + throw Error('config.ProviderRegistry is missing or is not an address.'); + } + + if ( + !providerRegistryOwner || + !isAddress(providerRegistryOwner) || + isZeroAddress(providerRegistryOwner) + ) { + throw Error('config.ProviderRegistryOwner is missing or is not an address.'); + } + + // Checks if deployer address is registry owner + if (process.env.MAINNET_FORK === 'true') { + await DRE.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [providerRegistryOwner], + }); + signer = DRE.ethers.provider.getSigner(providerRegistryOwner); + } else { + signer = await getFirstSigner(); + const deployerAddress = await signer.getAddress(); + if (providerRegistryOwner !== (await signer.getAddress())) { + throw Error( + `Current signer is not provider registry owner. \nCurrent deployer address: ${deployerAddress} \nExpected address: ${poolConfig.ProviderRegistryOwner}` + ); + } + } + // 1. Address Provider Registry instance + + const addressesProviderRegistry = ( + await getLendingPoolAddressesProviderRegistry(providerRegistryAddress) + ).connect(signer); + + console.log('Registry Address', addressesProviderRegistry.address); + + // 2. Deploy address provider and set genesis manager const addressesProvider = await deployLendingPoolAddressesProvider(MarketId, verify); - await waitForTx(await addressesProvider.setPoolAdmin(await getGenesisPoolAdmin(poolConfig))); - await waitForTx(await addressesProvider.setEmergencyAdmin(await getEmergencyAdmin(poolConfig))); - - console.log('Pool Admin', await addressesProvider.getPoolAdmin()); - console.log('Emergency Admin', await addressesProvider.getEmergencyAdmin()); - - // If no provider registry is set, deploy lending pool address provider registry and register the address provider - const addressesProviderRegistry = notFalsyOrZeroAddress(providerRegistryAddress) - ? await getLendingPoolAddressesProviderRegistry(providerRegistryAddress) - : await deployLendingPoolAddressesProviderRegistry(verify); - + // 3. Set the provider at the Registry await waitForTx( await addressesProviderRegistry.registerAddressesProvider( addressesProvider.address, ProviderId ) ); + + // 4. Set pool admins + + await waitForTx(await addressesProvider.setPoolAdmin(await getGenesisPoolAdmin(poolConfig))); + await waitForTx(await addressesProvider.setEmergencyAdmin(await getEmergencyAdmin(poolConfig))); + + console.log('Pool Admin', await addressesProvider.getPoolAdmin()); + console.log('Emergency Admin', await addressesProvider.getEmergencyAdmin()); }); diff --git a/tasks/misc/print-config.ts b/tasks/misc/print-config.ts new file mode 100644 index 00000000..4d0cc333 --- /dev/null +++ b/tasks/misc/print-config.ts @@ -0,0 +1,72 @@ +import { task } from 'hardhat/config'; +import { ConfigNames, loadPoolConfig } from '../../helpers/configuration'; +import { + getAaveProtocolDataProvider, + getLendingPoolAddressesProvider, + getLendingPoolAddressesProviderRegistry, +} from '../../helpers/contracts-getters'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { DRE } from '../../helpers/misc-utils'; +import { eEthereumNetwork } from '../../helpers/types'; + +task('print-config', 'Inits the DRE, to have access to all the plugins') + .addOptionalParam('dataProvider', 'Address of AaveProtocolDataProvider') + .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) + .setAction(async ({ pool, dataProvider }, localBRE) => { + await localBRE.run('set-DRE'); + const network = + process.env.MAINNET_FORK === 'true' + ? eEthereumNetwork.main + : (localBRE.network.name as eEthereumNetwork); + const poolConfig = loadPoolConfig(pool); + + const providerRegistryAddress = getParamPerNetwork(poolConfig.ProviderRegistry, network); + + const providerRegistry = await getLendingPoolAddressesProviderRegistry(providerRegistryAddress); + + const providers = await providerRegistry.getAddressesProvidersList(); + + const addressesProvider = await getLendingPoolAddressesProvider(providers[0]); // Checks first provider + + console.log('Addresses Providers', providers.join(', ')); + console.log('Market Id: ', await addressesProvider.getMarketId()); + console.log('LendingPool Proxy:', await addressesProvider.getLendingPool()); + console.log( + 'Lending Pool Collateral Manager', + await addressesProvider.getLendingPoolCollateralManager() + ); + console.log( + 'Lending Pool Configurator proxy', + await addressesProvider.getLendingPoolConfigurator() + ); + console.log('Pool admin', await addressesProvider.getPoolAdmin()); + console.log('Emergency admin', await addressesProvider.getEmergencyAdmin()); + console.log('Price Oracle', await addressesProvider.getPriceOracle()); + console.log('Lending Rate Oracle', await addressesProvider.getLendingRateOracle()); + console.log('Lending Pool Data Provider', dataProvider); + const protocolDataProvider = await getAaveProtocolDataProvider(dataProvider); + + const fields = [ + 'decimals', + 'ltv', + 'liquidationThreshold', + 'liquidationBonus', + 'reserveFactor', + 'usageAsCollateralEnabled', + 'borrowingEnabled', + 'stableBorrowRateEnabled', + 'isActive', + 'isFrozen', + ]; + for (const [symbol, address] of Object.entries( + getParamPerNetwork(poolConfig.ReserveAssets, network) + )) { + console.log(`- ${symbol} asset config`); + console.log(` - reserve address: ${address}`); + + const reserveData = await protocolDataProvider.getReserveData(address); + fields.forEach((field, index) => { + console.log(` - ${field}:`, reserveData[index].toString()); + }); + } + }); diff --git a/tasks/misc/print-fork-config.ts b/tasks/misc/print-fork-config.ts new file mode 100644 index 00000000..3d7e2a4d --- /dev/null +++ b/tasks/misc/print-fork-config.ts @@ -0,0 +1,12 @@ +import { task } from 'hardhat/config'; +import { getAaveProtocolDataProvider } from '../../helpers/contracts-getters'; + +task('print-config:fork', 'Deploy development enviroment') + .addFlag('verify', 'Verify contracts at Etherscan') + .setAction(async ({ verify }, DRE) => { + await DRE.run('set-DRE'); + await DRE.run('aave:mainnet'); + + const dataProvider = await getAaveProtocolDataProvider(); + await DRE.run('print-config', { dataProvider: dataProvider.address, pool: 'Aave' }); + }); diff --git a/tasks/verifications/2_tokens.ts b/tasks/verifications/2_tokens.ts index 032135ad..8ec27d9f 100644 --- a/tasks/verifications/2_tokens.ts +++ b/tasks/verifications/2_tokens.ts @@ -1,23 +1,23 @@ -import {task} from 'hardhat/config'; -import {loadPoolConfig, ConfigNames, getWethAddress} from '../../helpers/configuration'; -import {ZERO_ADDRESS} from '../../helpers/constants'; +import { task } from 'hardhat/config'; +import { loadPoolConfig, ConfigNames, getWethAddress } from '../../helpers/configuration'; +import { ZERO_ADDRESS } from '../../helpers/constants'; import { getAddressById, getLendingPool, getLendingPoolAddressesProvider, getLendingPoolConfiguratorProxy, } from '../../helpers/contracts-getters'; -import {getParamPerNetwork} from '../../helpers/contracts-helpers'; -import {verifyContract} from '../../helpers/etherscan-verification'; -import {eEthereumNetwork, ICommonConfiguration, IReserveParams} from '../../helpers/types'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { verifyContract } from '../../helpers/etherscan-verification'; +import { eEthereumNetwork, ICommonConfiguration, IReserveParams } from '../../helpers/types'; task('verify:tokens', 'Deploy oracles for dev enviroment') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) - .setAction(async ({verify, all, pool}, localDRE) => { + .setAction(async ({ verify, all, pool }, localDRE) => { await localDRE.run('set-DRE'); const network = localDRE.network.name as eEthereumNetwork; const poolConfig = loadPoolConfig(pool); - const {ReserveAssets, ReservesConfig} = poolConfig as ICommonConfiguration; + const { ReserveAssets, ReservesConfig } = poolConfig as ICommonConfiguration; const addressesProvider = await getLendingPoolAddressesProvider(); const lendingPoolProxy = await getLendingPool(); @@ -40,6 +40,7 @@ task('verify:tokens', 'Deploy oracles for dev enviroment') } const { + optimalUtilizationRate, baseVariableBorrowRate, variableRateSlope1, variableRateSlope2, @@ -64,6 +65,7 @@ task('verify:tokens', 'Deploy oracles for dev enviroment') console.log(`\n- Verifying Strategy rate...\n`); await verifyContract(interestRateStrategyAddress, [ addressesProvider.address, + optimalUtilizationRate, baseVariableBorrowRate, variableRateSlope1, variableRateSlope2, diff --git a/test/helpers/make-suite.ts b/test/helpers/make-suite.ts index 92b77e24..b30111b8 100644 --- a/test/helpers/make-suite.ts +++ b/test/helpers/make-suite.ts @@ -12,7 +12,7 @@ import { getWETHMocked, getWETHGateway, } from '../../helpers/contracts-getters'; -import { tEthereumAddress } from '../../helpers/types'; +import { eEthereumNetwork, tEthereumAddress } from '../../helpers/types'; import { LendingPool } from '../../types/LendingPool'; import { AaveProtocolDataProvider } from '../../types/AaveProtocolDataProvider'; import { MintableERC20 } from '../../types/MintableERC20'; @@ -26,10 +26,11 @@ 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'; +import { getEthersSigners, getParamPerNetwork } from '../../helpers/contracts-helpers'; import { WETH9Mocked } from '../../types/WETH9Mocked'; import { WETHGateway } from '../../types/WETHGateway'; import { solidity } from 'ethereum-waffle'; +import { AaveConfig } from '../../markets/aave'; chai.use(bignumberChai()); chai.use(almostEqual()); @@ -100,9 +101,16 @@ export async function initializeMakeSuite() { testEnv.configurator = await getLendingPoolConfiguratorProxy(); - testEnv.oracle = await getPriceOracle(); testEnv.addressesProvider = await getLendingPoolAddressesProvider(); - testEnv.registry = await getLendingPoolAddressesProviderRegistry(); + + if (process.env.MAINNET_FORK === 'true') { + testEnv.registry = await getLendingPoolAddressesProviderRegistry( + getParamPerNetwork(AaveConfig.ProviderRegistry, eEthereumNetwork.main) + ); + } else { + testEnv.registry = await getLendingPoolAddressesProviderRegistry(); + testEnv.oracle = await getPriceOracle(); + } testEnv.helpersContract = await getAaveProtocolDataProvider();