From 88a2cb21f4a7d6fcb32d608a20b720022e065edc Mon Sep 17 00:00:00 2001 From: David Racero Date: Thu, 15 Oct 2020 13:57:03 +0200 Subject: [PATCH 01/33] Move contract getters to their own file. Use factory connect. Fix imports --- helpers/contracts-getters.ts | 193 +++++++++++++++++ helpers/contracts-helpers.ts | 242 ++-------------------- tasks/dev/3_lending_pool.ts | 8 +- tasks/dev/4_oracles.ts | 9 +- tasks/dev/5_initialize.ts | 10 +- tasks/full/1_address_provider_registry.ts | 2 +- tasks/full/2_lending_pool.ts | 8 +- tasks/full/3_oracles.ts | 6 +- tasks/full/5_initialize.ts | 9 +- test/__setup.spec.ts | 8 +- test/addresses-provider-registry.spec.ts | 3 +- 11 files changed, 250 insertions(+), 248 deletions(-) diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index e69de29b..74f77627 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -0,0 +1,193 @@ +import { + AaveProtocolTestHelpersFactory, + ATokenFactory, + DefaultReserveInterestRateStrategyFactory, + LendingPoolAddressesProviderFactory, + LendingPoolAddressesProviderRegistryFactory, + LendingPoolConfiguratorFactory, + LendingPoolFactory, + LendingRateOracleFactory, + MintableErc20Factory, + MockFlashLoanReceiverFactory, + MockSwapAdapterFactory, + PriceOracleFactory, + 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 getLendingPoolAddressesProvider = async (address?: tEthereumAddress) => + await LendingPoolAddressesProviderFactory.connect( + address || + (await getDb().get(`${eContractid.LendingPoolAddressesProvider}.${BRE.network.name}`).value()) + .address, + BRE.ethers.provider + ); + +export const getLendingPoolConfiguratorProxy = async (address?: tEthereumAddress) => { + return await LendingPoolConfiguratorFactory.connect( + address || + (await getDb().get(`${eContractid.LendingPoolConfigurator}.${BRE.network.name}`).value()) + .address, + BRE.ethers.provider + ); +}; + +export const getLendingPool = async (address?: tEthereumAddress) => + await LendingPoolFactory.connect( + address || + (await getDb().get(`${eContractid.LendingPool}.${BRE.network.name}`).value()).address, + BRE.ethers.provider + ); + +export const getPriceOracle = async (address?: tEthereumAddress) => + await PriceOracleFactory.connect( + address || + (await getDb().get(`${eContractid.PriceOracle}.${BRE.network.name}`).value()).address, + BRE.ethers.provider + ); + +export const getAToken = async (address?: tEthereumAddress) => + await ATokenFactory.connect( + address || (await getDb().get(`${eContractid.AToken}.${BRE.network.name}`).value()).address, + BRE.ethers.provider + ); + +export const getStableDebtToken = async (address?: tEthereumAddress) => + await StableDebtTokenFactory.connect( + address || + (await getDb().get(`${eContractid.StableDebtToken}.${BRE.network.name}`).value()).address, + BRE.ethers.provider + ); + +export const getVariableDebtToken = async (address?: tEthereumAddress) => + await VariableDebtTokenFactory.connect( + address || + (await getDb().get(`${eContractid.VariableDebtToken}.${BRE.network.name}`).value()).address, + BRE.ethers.provider + ); + +export const getMintableErc20 = async (address: tEthereumAddress) => + await MintableErc20Factory.connect( + address || + (await getDb().get(`${eContractid.MintableERC20}.${BRE.network.name}`).value()).address, + BRE.ethers.provider + ); + +export const getIErc20Detailed = async (address: tEthereumAddress) => + await Ierc20DetailedFactory.connect( + address || + (await getDb().get(`${eContractid.IERC20Detailed}.${BRE.network.name}`).value()).address, + BRE.ethers.provider + ); + +export const getAaveProtocolTestHelpers = async (address?: tEthereumAddress) => + await AaveProtocolTestHelpersFactory.connect( + address || + (await getDb().get(`${eContractid.AaveProtocolTestHelpers}.${BRE.network.name}`).value()) + .address, + BRE.ethers.provider + ); + +export const getInterestRateStrategy = async (address?: tEthereumAddress) => + await DefaultReserveInterestRateStrategyFactory.connect( + address || + ( + await getDb() + .get(`${eContractid.DefaultReserveInterestRateStrategy}.${BRE.network.name}`) + .value() + ).address, + BRE.ethers.provider + ); + +export const getMockFlashLoanReceiver = async (address?: tEthereumAddress) => + await MockFlashLoanReceiverFactory.connect( + address || + (await getDb().get(`${eContractid.MockFlashLoanReceiver}.${BRE.network.name}`).value()) + .address, + BRE.ethers.provider + ); + +export const getMockSwapAdapter = async (address?: tEthereumAddress) => + await MockSwapAdapterFactory.connect( + address || + (await getDb().get(`${eContractid.MockSwapAdapter}.${BRE.network.name}`).value()).address, + BRE.ethers.provider + ); + +export const getLendingRateOracle = async (address?: tEthereumAddress) => + await LendingRateOracleFactory.connect( + address || + (await getDb().get(`${eContractid.LendingRateOracle}.${BRE.network.name}`).value()).address, + BRE.ethers.provider + ); + +export const getMockedTokens = async (config: PoolConfiguration) => { + const tokenSymbols = config.ReserveSymbols; + const db = getDb(); + const tokens: MockTokenMap = await tokenSymbols.reduce>( + 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>( + 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, + BRE.ethers.provider + ); diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 77730b04..a7853cea 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -12,7 +12,6 @@ import { TokenContractId, iMultiPoolsAssets, IReserveParams, - ICommonConfiguration, PoolConfiguration, } from './types'; @@ -23,9 +22,6 @@ 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'; @@ -34,7 +30,6 @@ 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'; @@ -50,7 +45,15 @@ import {ZERO_ADDRESS} from './constants'; import {MockSwapAdapter} from '../types/MockSwapAdapter'; import {signTypedData_v4, TypedData} from 'eth-sig-util'; import {fromRpcSig, ECDSASignature} from 'ethereumjs-util'; -import {SignerWithAddress} from '../test/helpers/make-suite'; + +import { + ChainlinkProxyPriceProviderFactory, + LendingPoolCollateralManagerFactory, + LendingRateOracleFactory, + MockAggregatorFactory, + PriceOracleFactory, +} from '../types'; +import {getIErc20Detailed} from './contracts-getters'; export const registerContractInJsonDb = async (contractId: string, contractInstance: Contract) => { const currentNetwork = BRE.network.name; @@ -213,7 +216,7 @@ export const deployLendingPool = async (verify?: boolean) => { }; export const deployPriceOracle = async (verify?: boolean) => { - const instance = await deployContract(eContractid.PriceOracle, []); + const instance = await new PriceOracleFactory().deploy(); if (verify) { await verifyContract(eContractid.PriceOracle, instance.address, []); } @@ -221,7 +224,7 @@ export const deployPriceOracle = async (verify?: boolean) => { }; export const deployLendingRateOracle = async (verify?: boolean) => { - const instance = await deployContract(eContractid.LendingRateOracle, []); + const instance = await new LendingRateOracleFactory().deploy(); if (verify) { await verifyContract(eContractid.LendingRateOracle, instance.address, []); } @@ -229,8 +232,8 @@ export const deployLendingRateOracle = async (verify?: boolean) => { }; export const deployMockAggregator = async (price: tStringTokenSmallUnits, verify?: boolean) => { - const args = [price]; - const instance = await deployContract(eContractid.MockAggregator, args); + const args: [tStringTokenSmallUnits] = [price]; + const instance = await new MockAggregatorFactory().deploy(...args); if (verify) { await verifyContract(eContractid.MockAggregator, instance.address, args); } @@ -245,11 +248,12 @@ export const deployChainlinkProxyPriceProvider = async ( ], verify?: boolean ) => { - const args = [assetsAddresses, sourcesAddresses, fallbackOracleAddress]; - const instance = await deployContract( - eContractid.ChainlinkProxyPriceProvider, - args - ); + const args: [tEthereumAddress[], tEthereumAddress[], tEthereumAddress] = [ + assetsAddresses, + sourcesAddresses, + fallbackOracleAddress, + ]; + const instance = await new ChainlinkProxyPriceProviderFactory().deploy(...args); if (verify) { await verifyContract(eContractid.MockAggregator, instance.address, args); } @@ -257,8 +261,7 @@ export const deployChainlinkProxyPriceProvider = async ( }; export const getChainlingProxyPriceProvider = async (address?: tEthereumAddress) => - await getContract( - eContractid.ChainlinkProxyPriceProvider, + new ChainlinkProxyPriceProviderFactory().attach( address || (await getDb().get(`${eContractid.ChainlinkProxyPriceProvider}.${BRE.network.name}`).value()) .address @@ -438,132 +441,6 @@ export const deployGenericAToken = async ( return instance; }; -export const getLendingPoolAddressesProvider = async (address?: tEthereumAddress) => { - return await getContract( - eContractid.LendingPoolAddressesProvider, - address || - (await getDb().get(`${eContractid.LendingPoolAddressesProvider}.${BRE.network.name}`).value()) - .address - ); -}; - -export const getLendingPoolConfiguratorProxy = async (address?: tEthereumAddress) => { - return await getContract( - 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 ( - await factory.attach( - address || - (await getDb().get(`${eContractid.LendingPool}.${BRE.network.name}`).value()).address - ) - ); -}; - -export const getPriceOracle = async (address?: tEthereumAddress) => { - return await getContract( - eContractid.PriceOracle, - address || (await getDb().get(`${eContractid.PriceOracle}.${BRE.network.name}`).value()).address - ); -}; - -export const getAToken = async (address?: tEthereumAddress) => { - return await getContract( - eContractid.AToken, - address || (await getDb().get(`${eContractid.AToken}.${BRE.network.name}`).value()).address - ); -}; - -export const getStableDebtToken = async (address?: tEthereumAddress) => { - return await getContract( - eContractid.StableDebtToken, - address || - (await getDb().get(`${eContractid.StableDebtToken}.${BRE.network.name}`).value()).address - ); -}; - -export const getVariableDebtToken = async (address?: tEthereumAddress) => { - return await getContract( - eContractid.VariableDebtToken, - address || - (await getDb().get(`${eContractid.VariableDebtToken}.${BRE.network.name}`).value()).address - ); -}; - -export const getMintableErc20 = async (address: tEthereumAddress) => { - return await getContract( - eContractid.MintableERC20, - address || - (await getDb().get(`${eContractid.MintableERC20}.${BRE.network.name}`).value()).address - ); -}; - -export const getIErc20Detailed = async (address: tEthereumAddress) => { - return await getContract( - eContractid.IERC20Detailed, - address || - (await getDb().get(`${eContractid.IERC20Detailed}.${BRE.network.name}`).value()).address - ); -}; - -export const getAaveProtocolTestHelpers = async (address?: tEthereumAddress) => { - return await getContract( - eContractid.AaveProtocolTestHelpers, - address || - (await getDb().get(`${eContractid.AaveProtocolTestHelpers}.${BRE.network.name}`).value()) - .address - ); -}; - -export const getInterestRateStrategy = async (address?: tEthereumAddress) => { - return await getContract( - eContractid.DefaultReserveInterestRateStrategy, - address || - ( - await getDb() - .get(`${eContractid.DefaultReserveInterestRateStrategy}.${BRE.network.name}`) - .value() - ).address - ); -}; - -export const getMockFlashLoanReceiver = async (address?: tEthereumAddress) => { - return await getContract( - eContractid.MockFlashLoanReceiver, - address || - (await getDb().get(`${eContractid.MockFlashLoanReceiver}.${BRE.network.name}`).value()) - .address - ); -}; - -export const getMockSwapAdapter = async (address?: tEthereumAddress) => { - return await getContract( - eContractid.MockSwapAdapter, - address || - (await getDb().get(`${eContractid.MockSwapAdapter}.${BRE.network.name}`).value()).address - ); -}; - -export const getLendingRateOracle = async (address?: tEthereumAddress) => { - return await getContract( - eContractid.LendingRateOracle, - address || - (await getDb().get(`${eContractid.LendingRateOracle}.${BRE.network.name}`).value()).address - ); -}; - const linkBytecode = (artifact: Artifact, libraries: any) => { let bytecode = artifact.bytecode; @@ -688,68 +565,6 @@ export const deployMockTokens = async (config: PoolConfiguration, verify?: boole return tokens; }; -export const getMockedTokens = async (config: PoolConfiguration) => { - const tokenSymbols = config.ReserveSymbols; - const db = getDb(); - const tokens: MockTokenMap = await tokenSymbols.reduce>( - async (acc, tokenSymbol) => { - const accumulator = await acc; - const address = db.get(`${tokenSymbol.toUpperCase()}.${BRE.network.name}`).value().address; - accumulator[tokenSymbol] = await getContract( - 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>( - async (acc, tokenSymbol) => { - const accumulator = await acc; - const address = db.get(`${tokenSymbol.toUpperCase()}.${BRE.network.name}`).value().address; - accumulator[tokenSymbol] = await getContract( - 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, tokenAddresses: {[symbol: string]: tEthereumAddress}, @@ -798,7 +613,6 @@ export const initReserves = async ( stableRateSlope2, }, ] = (Object.entries(reservesParams) as [string, IReserveParams][])[reserveParamIndex]; - console.log('deploy def reserve'); const rateStrategyContract = await deployDefaultReserveInterestRateStrategy( [ lendingPoolAddressesProvider.address, @@ -811,7 +625,6 @@ export const initReserves = async ( verify ); - console.log('deploy stable deb totken ', assetSymbol); const stableDebtToken = await deployStableDebtToken( [ `Aave stable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, @@ -823,7 +636,6 @@ export const initReserves = async ( verify ); - console.log('deploy var deb totken ', assetSymbol); const variableDebtToken = await deployVariableDebtToken( [ `Aave variable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, @@ -835,7 +647,6 @@ export const initReserves = async ( verify ); - console.log('deploy a token ', assetSymbol); const aToken = await deployGenericAToken( [ lendingPool.address, @@ -855,7 +666,6 @@ export const initReserves = async ( } } - console.log('init reserve currency ', assetSymbol); await lendingPoolConfigurator.initReserve( tokenAddress, aToken.address, @@ -870,18 +680,6 @@ export const initReserves = async ( } }; -export const getLendingPoolAddressesProviderRegistry = async (address?: tEthereumAddress) => { - return await getContract( - eContractid.LendingPoolAddressesProviderRegistry, - address || - ( - await getDb() - .get(`${eContractid.LendingPoolAddressesProviderRegistry}.${BRE.network.name}`) - .value() - ).address - ); -}; - export const buildPermitParams = ( chainId: number, token: tEthereumAddress, diff --git a/tasks/dev/3_lending_pool.ts b/tasks/dev/3_lending_pool.ts index b7c88a19..82459557 100644 --- a/tasks/dev/3_lending_pool.ts +++ b/tasks/dev/3_lending_pool.ts @@ -1,14 +1,16 @@ 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'; +import { + getLendingPoolAddressesProvider, + getLendingPool, + getLendingPoolConfiguratorProxy, +} from '../../helpers/contracts-getters'; task('dev:deploy-lending-pool', 'Deploy lending pool for dev enviroment') .addOptionalParam('verify', 'Verify contracts at Etherscan') diff --git a/tasks/dev/4_oracles.ts b/tasks/dev/4_oracles.ts index 0e2d8ef5..5ab756d9 100644 --- a/tasks/dev/4_oracles.ts +++ b/tasks/dev/4_oracles.ts @@ -1,12 +1,8 @@ import {task} from '@nomiclabs/buidler/config'; import { - getLendingPoolAddressesProvider, deployPriceOracle, - getMockedTokens, - getPairsTokenAggregator, deployChainlinkProxyPriceProvider, deployLendingRateOracle, - getAllMockedTokens, } from '../../helpers/contracts-helpers'; import { @@ -18,6 +14,11 @@ import {ICommonConfiguration, iAssetBase, TokenContractId} from '../../helpers/t 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') diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index 6333247c..e504decd 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -1,15 +1,11 @@ import {task} from '@nomiclabs/buidler/config'; import { - getLendingPoolAddressesProvider, initReserves, deployLendingPoolCollateralManager, insertContractAddressInDb, deployMockFlashLoanReceiver, deployWalletBalancerProvider, deployAaveProtocolTestHelpers, - getLendingPool, - getLendingPoolConfiguratorProxy, - getAllMockedTokens, } from '../../helpers/contracts-helpers'; import {getReservesConfigByPool} from '../../helpers/configuration'; @@ -18,6 +14,12 @@ import {waitForTx, filterMapBy} from '../../helpers/misc-utils'; import {enableReservesToBorrow, enableReservesAsCollateral} 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'; task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') .addOptionalParam('verify', 'Verify contracts at Etherscan') diff --git a/tasks/full/1_address_provider_registry.ts b/tasks/full/1_address_provider_registry.ts index ef579579..11195e66 100644 --- a/tasks/full/1_address_provider_registry.ts +++ b/tasks/full/1_address_provider_registry.ts @@ -3,11 +3,11 @@ import { deployLendingPoolAddressesProvider, deployLendingPoolAddressesProviderRegistry, getParamPerNetwork, - getLendingPoolAddressesProviderRegistry, } from '../../helpers/contracts-helpers'; 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', diff --git a/tasks/full/2_lending_pool.ts b/tasks/full/2_lending_pool.ts index a4f919ce..5c3fb7f9 100644 --- a/tasks/full/2_lending_pool.ts +++ b/tasks/full/2_lending_pool.ts @@ -1,14 +1,16 @@ 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'; +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') diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index 3121b008..9d640448 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -1,7 +1,5 @@ import {task} from '@nomiclabs/buidler/config'; import { - getLendingPoolAddressesProvider, - getPairsTokenAggregator, deployChainlinkProxyPriceProvider, deployLendingRateOracle, getParamPerNetwork, @@ -12,6 +10,10 @@ import {ICommonConfiguration, eEthereumNetwork, SymbolMap} from '../../helpers/t 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') diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 31900897..1c54fd69 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -1,13 +1,9 @@ import {task} from '@nomiclabs/buidler/config'; import { - getLendingPoolAddressesProvider, initReserves, deployLendingPoolCollateralManager, - insertContractAddressInDb, deployWalletBalancerProvider, deployAaveProtocolTestHelpers, - getLendingPool, - getLendingPoolConfiguratorProxy, getParamPerNetwork, } from '../../helpers/contracts-helpers'; import {loadPoolConfig, ConfigNames} from '../../helpers/configuration'; @@ -17,6 +13,11 @@ import {waitForTx} from '../../helpers/misc-utils'; import {enableReservesToBorrow, enableReservesAsCollateral} from '../../helpers/init-helpers'; import {ZERO_ADDRESS} from '../../helpers/constants'; import {exit} from 'process'; +import { + getLendingPool, + getLendingPoolConfiguratorProxy, + getLendingPoolAddressesProvider, +} from '../../helpers/contracts-getters'; task('full:initialize-lending-pool', 'Initialize lending pool configuration.') .addFlag('verify', 'Verify contracts at Etherscan') diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index 676ae52a..5a40570e 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -7,17 +7,14 @@ import { deployLendingPoolConfigurator, deployLendingPool, deployPriceOracle, - getLendingPoolConfiguratorProxy, deployChainlinkProxyPriceProvider, deployLendingPoolCollateralManager, deployMockFlashLoanReceiver, deployWalletBalancerProvider, - getLendingPool, insertContractAddressInDb, deployAaveProtocolTestHelpers, getEthersSigners, registerContractInJsonDb, - getPairsTokenAggregator, initReserves, deployMockSwapAdapter, deployLendingRateOracle, @@ -38,6 +35,11 @@ import {waitForTx} from '../helpers/misc-utils'; import {enableReservesToBorrow, enableReservesAsCollateral} 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; diff --git a/test/addresses-provider-registry.spec.ts b/test/addresses-provider-registry.spec.ts index 457514e4..7baead04 100644 --- a/test/addresses-provider-registry.spec.ts +++ b/test/addresses-provider-registry.spec.ts @@ -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'); From 03504849f1396688855c0fe7518eb5bdcba2fee1 Mon Sep 17 00:00:00 2001 From: David Racero Date: Thu, 15 Oct 2020 19:19:02 +0200 Subject: [PATCH 02/33] Deployment function optimizations WIP --- deployed-contracts.json | 30 +-- helpers/contracts-getters.ts | 58 +++-- helpers/contracts-helpers.ts | 416 +++++++++++--------------------- helpers/init-helpers.ts | 129 +++++++++- helpers/misc-utils.ts | 2 + helpers/oracles-helpers.ts | 2 + test/__setup.spec.ts | 4 +- test/collateral-swap.spec.ts | 2 +- test/flashloan.spec.ts | 7 +- test/helpers/actions.ts | 7 +- test/helpers/make-suite.ts | 5 +- test/helpers/utils/helpers.ts | 4 +- test/pausable-functions.spec.ts | 3 +- test/upgradeability.spec.ts | 8 +- 14 files changed, 348 insertions(+), 329 deletions(-) diff --git a/deployed-contracts.json b/deployed-contracts.json index 7840c6ba..29cefb7c 100644 --- a/deployed-contracts.json +++ b/deployed-contracts.json @@ -97,7 +97,7 @@ }, "PriceOracle": { "buidlerevm": { - "address": "0x1750499D05Ed1674d822430FB960d5F6731fDf64", + "address": "0x0C6c3C47A1f650809B0D1048FDf9603e09473D7E", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -111,7 +111,7 @@ }, "MockAggregator": { "buidlerevm": { - "address": "0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89", + "address": "0xc11f8E173ee67ffA7BBdD185D2399994AAd23Ec6", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -125,7 +125,7 @@ }, "ChainlinkProxyPriceProvider": { "buidlerevm": { - "address": "0x7B6C3e5486D9e6959441ab554A889099eed76290", + "address": "0xD662fb7FDC7526C79AA4417d2A4415416e057ec4", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -143,7 +143,7 @@ }, "LendingRateOracle": { "buidlerevm": { - "address": "0xD83D2773a7873ae2b5f8Fb92097e20a8C64F691E", + "address": "0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -161,7 +161,7 @@ }, "DefaultReserveInterestRateStrategy": { "buidlerevm": { - "address": "0xB660Fdd109a95718cB9d20E3A89EE6cE342aDcB6", + "address": "0x7d40dD74d3aE1a7e4A7dd08eaE899e85940563cd", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -220,7 +220,7 @@ }, "MockFlashLoanReceiver": { "buidlerevm": { - "address": "0xBEF0d4b9c089a5883741fC14cbA352055f35DDA2" + "address": "0x63387deC8C4a0F17Cf0C27Ea3476F03F6a45d3AE" }, "localhost": { "address": "0x2B681757d757fbB80cc51c6094cEF5eE75bF55aA" @@ -231,7 +231,7 @@ }, "WalletBalanceProvider": { "buidlerevm": { - "address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4", + "address": "0x2B681757d757fbB80cc51c6094cEF5eE75bF55aA", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -567,7 +567,7 @@ }, "AaveProtocolTestHelpers": { "buidlerevm": { - "address": "0xe7536f450378748E1BD4645D3c77ec38e0F3ba28" + "address": "0x93472C0e03215F9c33DA240Eb16703C8244eAa8c" }, "localhost": { "address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4" @@ -578,7 +578,7 @@ }, "StableDebtToken": { "buidlerevm": { - "address": "0x830bceA96E56DBC1F8578f75fBaC0AF16B32A07d", + "address": "0x5f687ea375c359E0CF6aa8A1004BE0c3BaBee7Fd", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -592,7 +592,7 @@ }, "VariableDebtToken": { "buidlerevm": { - "address": "0xA0AB1cB92A4AF81f84dCd258155B5c25D247b54E", + "address": "0x626FdE749F9d499d3777320CAf29484B624ab84a", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -610,7 +610,7 @@ "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "buidlerevm": { - "address": "0x5f7134cd38C826a7649f9Cc47dda24d834DD2967", + "address": "0xB660Fdd109a95718cB9d20E3A89EE6cE342aDcB6", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "coverage": { @@ -620,7 +620,7 @@ }, "MockAToken": { "buidlerevm": { - "address": "0x392E5355a0e88Bd394F717227c752670fb3a8020", + "address": "0xBEF0d4b9c089a5883741fC14cbA352055f35DDA2", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -648,7 +648,7 @@ }, "MockStableDebtToken": { "buidlerevm": { - "address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460", + "address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -662,7 +662,7 @@ }, "MockVariableDebtToken": { "buidlerevm": { - "address": "0xEBAB67ee3ef604D5c250A53b4b8fcbBC6ec3007C", + "address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -676,7 +676,7 @@ }, "MockSwapAdapter": { "buidlerevm": { - "address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10" + "address": "0x8280D40C9E9F04229D2435EAad6e0011309ce81B" }, "coverage": { "address": "0xBEF0d4b9c089a5883741fC14cbA352055f35DDA2" diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index 74f77627..5ab75f07 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -2,6 +2,7 @@ import { AaveProtocolTestHelpersFactory, ATokenFactory, DefaultReserveInterestRateStrategyFactory, + GenericLogicFactory, LendingPoolAddressesProviderFactory, LendingPoolAddressesProviderRegistryFactory, LendingPoolConfiguratorFactory, @@ -11,20 +12,23 @@ import { MockFlashLoanReceiverFactory, MockSwapAdapterFactory, PriceOracleFactory, + ReserveLogicFactory, StableDebtTokenFactory, VariableDebtTokenFactory, } from '../types'; import {Ierc20DetailedFactory} from '../types/Ierc20DetailedFactory'; -import {MockTokenMap} from './contracts-helpers'; +import {getContract, 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, - BRE.ethers.provider + await getFirstSigner() ); export const getLendingPoolConfiguratorProxy = async (address?: tEthereumAddress) => { @@ -32,7 +36,7 @@ export const getLendingPoolConfiguratorProxy = async (address?: tEthereumAddress address || (await getDb().get(`${eContractid.LendingPoolConfigurator}.${BRE.network.name}`).value()) .address, - BRE.ethers.provider + await getFirstSigner() ); }; @@ -40,48 +44,48 @@ export const getLendingPool = async (address?: tEthereumAddress) => await LendingPoolFactory.connect( address || (await getDb().get(`${eContractid.LendingPool}.${BRE.network.name}`).value()).address, - BRE.ethers.provider + await getFirstSigner() ); export const getPriceOracle = async (address?: tEthereumAddress) => await PriceOracleFactory.connect( address || (await getDb().get(`${eContractid.PriceOracle}.${BRE.network.name}`).value()).address, - BRE.ethers.provider + await getFirstSigner() ); export const getAToken = async (address?: tEthereumAddress) => await ATokenFactory.connect( address || (await getDb().get(`${eContractid.AToken}.${BRE.network.name}`).value()).address, - BRE.ethers.provider + await getFirstSigner() ); export const getStableDebtToken = async (address?: tEthereumAddress) => await StableDebtTokenFactory.connect( address || (await getDb().get(`${eContractid.StableDebtToken}.${BRE.network.name}`).value()).address, - BRE.ethers.provider + await getFirstSigner() ); export const getVariableDebtToken = async (address?: tEthereumAddress) => await VariableDebtTokenFactory.connect( address || (await getDb().get(`${eContractid.VariableDebtToken}.${BRE.network.name}`).value()).address, - BRE.ethers.provider + await getFirstSigner() ); export const getMintableErc20 = async (address: tEthereumAddress) => await MintableErc20Factory.connect( address || (await getDb().get(`${eContractid.MintableERC20}.${BRE.network.name}`).value()).address, - BRE.ethers.provider + await getFirstSigner() ); export const getIErc20Detailed = async (address: tEthereumAddress) => await Ierc20DetailedFactory.connect( address || (await getDb().get(`${eContractid.IERC20Detailed}.${BRE.network.name}`).value()).address, - BRE.ethers.provider + await getFirstSigner() ); export const getAaveProtocolTestHelpers = async (address?: tEthereumAddress) => @@ -89,7 +93,7 @@ export const getAaveProtocolTestHelpers = async (address?: tEthereumAddress) => address || (await getDb().get(`${eContractid.AaveProtocolTestHelpers}.${BRE.network.name}`).value()) .address, - BRE.ethers.provider + await getFirstSigner() ); export const getInterestRateStrategy = async (address?: tEthereumAddress) => @@ -100,7 +104,7 @@ export const getInterestRateStrategy = async (address?: tEthereumAddress) => .get(`${eContractid.DefaultReserveInterestRateStrategy}.${BRE.network.name}`) .value() ).address, - BRE.ethers.provider + await getFirstSigner() ); export const getMockFlashLoanReceiver = async (address?: tEthereumAddress) => @@ -108,21 +112,21 @@ export const getMockFlashLoanReceiver = async (address?: tEthereumAddress) => address || (await getDb().get(`${eContractid.MockFlashLoanReceiver}.${BRE.network.name}`).value()) .address, - BRE.ethers.provider + await getFirstSigner() ); export const getMockSwapAdapter = async (address?: tEthereumAddress) => await MockSwapAdapterFactory.connect( address || (await getDb().get(`${eContractid.MockSwapAdapter}.${BRE.network.name}`).value()).address, - BRE.ethers.provider + await getFirstSigner() ); export const getLendingRateOracle = async (address?: tEthereumAddress) => await LendingRateOracleFactory.connect( address || (await getDb().get(`${eContractid.LendingRateOracle}.${BRE.network.name}`).value()).address, - BRE.ethers.provider + await getFirstSigner() ); export const getMockedTokens = async (config: PoolConfiguration) => { @@ -189,5 +193,27 @@ export const getLendingPoolAddressesProviderRegistry = async (address?: tEthereu .get(`${eContractid.LendingPoolAddressesProviderRegistry}.${BRE.network.name}`) .value() ).address, - BRE.ethers.provider + await getFirstSigner() + ); + +export const getReserveLogicLibrary = async (address?: tEthereumAddress) => + await ReserveLogicFactory.connect( + address || + ( + await getDb() + .get(`${eContractid.LendingPoolAddressesProviderRegistry}.${BRE.network.name}`) + .value() + ).address, + await getFirstSigner() + ); + +export const getGenericLogic = async (address?: tEthereumAddress) => + await GenericLogicFactory.connect( + address || + ( + await getDb() + .get(`${eContractid.LendingPoolAddressesProviderRegistry}.${BRE.network.name}`) + .value() + ).address, + await getFirstSigner() ); diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index a7853cea..deef66e1 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -15,16 +15,10 @@ import { 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 {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'; @@ -35,7 +29,7 @@ import {VariableDebtToken} from '../types/VariableDebtToken'; import {MockContract} from 'ethereum-waffle'; import {getReservesConfigByPool} from './configuration'; import {verifyContract} from './etherscan-verification'; - +import {getFirstSigner, getGenericLogic} from './contracts-getters'; const { ProtocolGlobalParams: {UsdAddress}, } = CommonsConfig; @@ -45,15 +39,25 @@ import {ZERO_ADDRESS} from './constants'; import {MockSwapAdapter} from '../types/MockSwapAdapter'; import {signTypedData_v4, TypedData} from 'eth-sig-util'; import {fromRpcSig, ECDSASignature} from 'ethereumjs-util'; - +import {getIErc20Detailed} from './contracts-getters'; import { ChainlinkProxyPriceProviderFactory, + GenericLogicFactory, + InitializableAdminUpgradeabilityProxyFactory, + LendingPoolAddressesProviderFactory, + LendingPoolAddressesProviderRegistryFactory, LendingPoolCollateralManagerFactory, + LendingPoolConfiguratorFactory, + LendingPoolFactory, + LendingPoolLibraryAddresses, LendingRateOracleFactory, MockAggregatorFactory, + MockFlashLoanReceiverFactory, + MockSwapAdapterFactory, PriceOracleFactory, + ReserveLogicFactory, + WalletBalanceProviderFactory, } from '../types'; -import {getIErc20Detailed} from './contracts-getters'; export const registerContractInJsonDb = async (contractId: string, contractInstance: Contract) => { const currentNetwork = BRE.network.name; @@ -109,71 +113,69 @@ export const deployContract = async ( return contract; }; +export const withSaveAndVerify = async ( + instance: Contract, + id: string, + args: (string | string[])[], + verify?: boolean +) => { + await registerContractInJsonDb(id, instance); + if (verify) { + await verifyContract(id, instance.address, args); + } + return instance; +}; + export const getContract = async ( contractName: string, address: string ): Promise => (await BRE.ethers.getContractAt(contractName, address)) as ContractType; -export const deployLendingPoolAddressesProvider = async (verify?: boolean) => { - const instance = await deployContract( +export const deployLendingPoolAddressesProvider = async (verify?: boolean) => + withSaveAndVerify( + await new LendingPoolAddressesProviderFactory(await getFirstSigner()).deploy(), eContractid.LendingPoolAddressesProvider, - [] + [], + verify ); - if (verify) { - await verifyContract(eContractid.LendingPoolAddressesProvider, instance.address, []); - } - return instance; -}; -export const deployLendingPoolAddressesProviderRegistry = async (verify?: boolean) => { - const instance = await deployContract( +export const deployLendingPoolAddressesProviderRegistry = async (verify?: boolean) => + withSaveAndVerify( + await new LendingPoolAddressesProviderRegistryFactory(await getFirstSigner()).deploy(), eContractid.LendingPoolAddressesProviderRegistry, - [] + [], + verify ); - if (verify) { - await verifyContract(eContractid.LendingPoolAddressesProviderRegistry, instance.address, []); - } - return instance; -}; -export const deployLendingPoolConfigurator = async (verify?: boolean) => { - const instance = await deployContract( +export const deployLendingPoolConfigurator = async (verify?: boolean) => + withSaveAndVerify( + await new LendingPoolConfiguratorFactory(await getFirstSigner()).deploy(), 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 + [], + verify ); - const linkedGenericLogicByteCode = linkBytecode(genericLogicArtifact, { - [eContractid.ReserveLogic]: reserveLogic.address, - }); - - const genericLogicFactory = await BRE.ethers.getContractFactory( - genericLogicArtifact.abi, - linkedGenericLogicByteCode +export const deployReserveLogicLibrary = async (verify?: boolean) => + withSaveAndVerify( + await new ReserveLogicFactory(await getFirstSigner()).deploy(), + eContractid.ReserveLogic, + [], + verify ); - const genericLogic = await (await genericLogicFactory.deploy()).deployed(); +export const deployGenericLogic = async (verify?: boolean) => + withSaveAndVerify( + await new GenericLogicFactory(await getFirstSigner()).deploy(), + eContractid.GenericLogic, + [], + verify + ); +export const deployValidationLogic = async ( + reserveLogic: Contract, + genericLogic: Contract, + verify?: boolean +) => { const validationLogicArtifact = await readArtifact( BRE.config.paths.artifacts, eContractid.ValidationLogic @@ -191,141 +193,122 @@ export const linkLibrariesToArtifact = async (artifact: Artifact) => { 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 withSaveAndVerify(validationLogic, eContractid.ValidationLogic, [], verify); +}; - return factory; +export const deployAaveLibraries = async ( + verify?: boolean +): Promise => { + const reserveLogic = await deployReserveLogicLibrary(verify); + const genericLogic = await deployGenericLogic(verify); + const validationLogic = await deployValidationLogic(reserveLogic, genericLogic, verify); + + // Hardcoded solidity placeholders, if any library changes path this will fail. + // Placeholder can be calculated via solidity keccak, but the LendingPoolLibraryAddresses Type seems to + // require a hardcoded string. + // + // how-to: PLACEHOLDER = solidityKeccak256(['string'], `${libPath}:${libName}`).slice(2, 36) + // '__$PLACEHOLDER$__' + // or grab placeholdes from LendingPoolLibraryAddresses at Typechain generation. + return { + ['__$5201a97c05ba6aa659e2f36a933dd51801$__']: reserveLogic.address, + ['__$d3b4366daeb9cadc7528af6145b50b2183$__']: genericLogic.address, + ['__$4c26be947d349222af871a3168b3fe584b$__']: validationLogic.address, + }; }; export const deployLendingPool = async (verify?: boolean) => { - const lendingPoolArtifact = await readArtifact( - BRE.config.paths.artifacts, - eContractid.LendingPool + const libraries = await deployAaveLibraries(verify); + return withSaveAndVerify( + await new LendingPoolFactory(libraries, await getFirstSigner()).deploy(), + eContractid.LendingPool, + [], + verify ); - const factory = await linkLibrariesToArtifact(lendingPoolArtifact); - const lendingPool = await factory.deploy(); - 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 new PriceOracleFactory().deploy(); - if (verify) { - await verifyContract(eContractid.PriceOracle, instance.address, []); - } - return instance; -}; +export const deployPriceOracle = async (verify?: boolean) => + withSaveAndVerify( + await new PriceOracleFactory(await getFirstSigner()).deploy(), + eContractid.PriceOracle, + [], + verify + ); -export const deployLendingRateOracle = async (verify?: boolean) => { - const instance = await new LendingRateOracleFactory().deploy(); - if (verify) { - await verifyContract(eContractid.LendingRateOracle, instance.address, []); - } - return instance; -}; +export const deployLendingRateOracle = async (verify?: boolean) => + withSaveAndVerify( + await new LendingRateOracleFactory(await getFirstSigner()).deploy(), + eContractid.LendingRateOracle, + [], + verify + ); -export const deployMockAggregator = async (price: tStringTokenSmallUnits, verify?: boolean) => { - const args: [tStringTokenSmallUnits] = [price]; - const instance = await new MockAggregatorFactory().deploy(...args); - if (verify) { - await verifyContract(eContractid.MockAggregator, instance.address, args); - } - return instance; -}; +export const deployMockAggregator = async (price: tStringTokenSmallUnits, verify?: boolean) => + withSaveAndVerify( + await new MockAggregatorFactory(await getFirstSigner()).deploy(price), + eContractid.MockAggregator, + [price], + verify + ); export const deployChainlinkProxyPriceProvider = async ( - [assetsAddresses, sourcesAddresses, fallbackOracleAddress]: [ - tEthereumAddress[], - tEthereumAddress[], - tEthereumAddress - ], + args: [tEthereumAddress[], tEthereumAddress[], tEthereumAddress], verify?: boolean -) => { - const args: [tEthereumAddress[], tEthereumAddress[], tEthereumAddress] = [ - assetsAddresses, - sourcesAddresses, - fallbackOracleAddress, - ]; - const instance = await new ChainlinkProxyPriceProviderFactory().deploy(...args); - if (verify) { - await verifyContract(eContractid.MockAggregator, instance.address, args); - } - return instance; -}; - -export const getChainlingProxyPriceProvider = async (address?: tEthereumAddress) => - new ChainlinkProxyPriceProviderFactory().attach( - address || - (await getDb().get(`${eContractid.ChainlinkProxyPriceProvider}.${BRE.network.name}`).value()) - .address +) => + withSaveAndVerify( + await new ChainlinkProxyPriceProviderFactory(await getFirstSigner()).deploy(...args), + eContractid.ChainlinkProxyPriceProvider, + args, + verify ); export const deployLendingPoolCollateralManager = async (verify?: boolean) => { - const collateralManagerArtifact = await readArtifact( - BRE.config.paths.artifacts, - eContractid.LendingPoolCollateralManager + const genericLogic = await getGenericLogic(); + const libraries = { + // See deployAaveLibraries() function + ['__$d3b4366daeb9cadc7528af6145b50b2183$__']: genericLogic.address, + }; + + return withSaveAndVerify( + await new LendingPoolCollateralManagerFactory(libraries, await getFirstSigner()).deploy(), + eContractid.LendingPoolCollateralManager, + [], + verify ); - - 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( +export const deployInitializableAdminUpgradeabilityProxy = async (verify?: boolean) => + withSaveAndVerify( + await new InitializableAdminUpgradeabilityProxyFactory(await getFirstSigner()).deploy(), eContractid.InitializableAdminUpgradeabilityProxy, - [] + [], + verify ); - 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( +) => + withSaveAndVerify( + await new MockFlashLoanReceiverFactory(await getFirstSigner()).deploy(addressesProvider), eContractid.MockFlashLoanReceiver, - args + [addressesProvider], + verify ); - 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( +) => + withSaveAndVerify( + await new WalletBalanceProviderFactory(await getFirstSigner()).deploy(addressesProvider), eContractid.WalletBalanceProvider, - args + [addressesProvider], + verify ); - if (verify) { - await verifyContract(eContractid.WalletBalanceProvider, instance.address, args); - } - return instance; -}; + export const deployMockSwapAdapter = async (addressesProvider: tEthereumAddress) => - await deployContract(eContractid.MockSwapAdapter, [addressesProvider]); + await new MockSwapAdapterFactory(await getFirstSigner()).deploy(addressesProvider); export const deployAaveProtocolTestHelpers = async ( addressesProvider: tEthereumAddress, @@ -565,121 +548,6 @@ export const deployMockTokens = async (config: PoolConfiguration, verify?: boole return tokens; }; -export const initReserves = async ( - reservesParams: iMultiPoolsAssets, - 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]; - const rateStrategyContract = await deployDefaultReserveInterestRateStrategy( - [ - lendingPoolAddressesProvider.address, - baseVariableBorrowRate, - variableRateSlope1, - variableRateSlope2, - stableRateSlope1, - stableRateSlope2, - ], - verify - ); - - const stableDebtToken = await deployStableDebtToken( - [ - `Aave stable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, - `stableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, - tokenAddress, - lendingPool.address, - incentivesController, - ], - verify - ); - - const variableDebtToken = await deployVariableDebtToken( - [ - `Aave variable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, - `variableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, - tokenAddress, - lendingPool.address, - incentivesController, - ], - verify - ); - - 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'); - } - } - - 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 buildPermitParams = ( chainId: number, token: tEthereumAddress, diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 6e049c51..a2fc3099 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -1,7 +1,14 @@ -import {iMultiPoolsAssets, IReserveParams, tEthereumAddress} from './types'; +import {AavePools, iMultiPoolsAssets, IReserveParams, tEthereumAddress} from './types'; import {LendingPool} from '../types/LendingPool'; import {LendingPoolConfigurator} from '../types/LendingPoolConfigurator'; import {AaveProtocolTestHelpers} from '../types/AaveProtocolTestHelpers'; +import {LendingPoolAddressesProvider} from '../types/LendingPoolAddressesProvider'; +import { + deployDefaultReserveInterestRateStrategy, + deployStableDebtToken, + deployVariableDebtToken, + deployGenericAToken, +} from './contracts-helpers'; export const enableReservesToBorrow = async ( reservesParams: iMultiPoolsAssets, @@ -79,3 +86,123 @@ export const enableReservesAsCollateral = async ( } } }; + +export const initReserves = async ( + reservesParams: iMultiPoolsAssets, + 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( + [ + `Aave stable debt bearing ${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, + `stableDebt${assetSymbol === 'WETH' ? 'ETH' : assetSymbol}`, + tokenAddress, + lendingPool.address, + incentivesController, + ], + verify + ); + + console.log('- Deploy var deb totken ', 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 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 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.`); + } + } +}; diff --git a/helpers/misc-utils.ts b/helpers/misc-utils.ts index 67ac7fe2..4156af63 100644 --- a/helpers/misc-utils.ts +++ b/helpers/misc-utils.ts @@ -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(); diff --git a/helpers/oracles-helpers.ts b/helpers/oracles-helpers.ts index b3439df9..f87f54b3 100644 --- a/helpers/oracles-helpers.ts +++ b/helpers/oracles-helpers.ts @@ -47,7 +47,9 @@ export const setInitialAssetPricesInOracle = async ( const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[ assetAddressIndex ]; + console.log('PRIOR'); await waitForTx(await priceOracleInstance.setAssetPrice(assetAddress, price)); + console.log('AFTA'); } }; diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index 5a40570e..6a02b940 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -93,7 +93,6 @@ 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'); @@ -153,7 +152,10 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { fallbackOracle ); + console.log('setted prices'); + console.log('prior mocks'); const mockAggregators = await deployAllMockAggregators(MOCK_CHAINLINK_AGGREGATORS_PRICES); + console.log('aftahlocks'); const allTokenAddresses = Object.entries(mockTokens).reduce( (accum: {[tokenSymbol: string]: tEthereumAddress}, [tokenSymbol, tokenContract]) => ({ diff --git a/test/collateral-swap.spec.ts b/test/collateral-swap.spec.ts index b85e1dd3..6921b204 100644 --- a/test/collateral-swap.spec.ts +++ b/test/collateral-swap.spec.ts @@ -1,6 +1,6 @@ import {makeSuite, TestEnv} from './helpers/make-suite'; import {MockSwapAdapter} from '../types/MockSwapAdapter'; -import {getMockSwapAdapter} from '../helpers/contracts-helpers'; +import {getMockSwapAdapter} from '../helpers/contracts-getters'; import {ProtocolErrors} from '../helpers/types'; import {ethers} from 'ethers'; import {APPROVAL_AMOUNT_LENDING_POOL} from '../helpers/constants'; diff --git a/test/flashloan.spec.ts b/test/flashloan.spec.ts index b4274a5a..7eafcf75 100644 --- a/test/flashloan.spec.ts +++ b/test/flashloan.spec.ts @@ -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'); diff --git a/test/helpers/actions.ts b/test/helpers/actions.ts index 85d3eb00..0ab80a21 100644 --- a/test/helpers/actions.ts +++ b/test/helpers/actions.ts @@ -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'; diff --git a/test/helpers/make-suite.ts b/test/helpers/make-suite.ts index 5eb8788f..29b1f546 100644 --- a/test/helpers/make-suite.ts +++ b/test/helpers/make-suite.ts @@ -1,7 +1,6 @@ import {evmRevert, evmSnapshot, BRE} from '../../helpers/misc-utils'; import {Signer} from 'ethers'; import { - getEthersSigners, getLendingPool, getLendingPoolAddressesProvider, getAaveProtocolTestHelpers, @@ -11,7 +10,7 @@ import { getPriceOracle, getMockSwapAdapter, getLendingPoolAddressesProviderRegistry, -} from '../../helpers/contracts-helpers'; +} from '../../helpers/contracts-getters'; import {tEthereumAddress} from '../../helpers/types'; import {LendingPool} from '../../types/LendingPool'; import {AaveProtocolTestHelpers} from '../../types/AaveProtocolTestHelpers'; @@ -27,6 +26,8 @@ import {PriceOracle} from '../../types/PriceOracle'; import {LendingPoolAddressesProvider} from '../../types/LendingPoolAddressesProvider'; import {MockSwapAdapter} from '../../types/MockSwapAdapter'; import {LendingPoolAddressesProviderRegistry} from '../../types/LendingPoolAddressesProviderRegistry'; +import {getEthersSigners} from '../../helpers/contracts-helpers'; +import {AaveProtocolTestHelpersFactory} from '../../types'; chai.use(bignumberChai()); chai.use(almostEqual()); diff --git a/test/helpers/utils/helpers.ts b/test/helpers/utils/helpers.ts index d729d327..7a909c20 100644 --- a/test/helpers/utils/helpers.ts +++ b/test/helpers/utils/helpers.ts @@ -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(); diff --git a/test/pausable-functions.spec.ts b/test/pausable-functions.spec.ts index d5e321e3..3649e03c 100644 --- a/test/pausable-functions.spec.ts +++ b/test/pausable-functions.spec.ts @@ -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'); diff --git a/test/upgradeability.spec.ts b/test/upgradeability.spec.ts index 45beb11c..72d818d7 100644 --- a/test/upgradeability.spec.ts +++ b/test/upgradeability.spec.ts @@ -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; From 7556f25c1a454e1f1c775e187e0f7d00df4288bc Mon Sep 17 00:00:00 2001 From: David Racero Date: Thu, 15 Oct 2020 20:28:12 +0200 Subject: [PATCH 03/33] Moved all deployments outside of helpers with wrapper. --- helpers/contracts-deployments.ts | 348 ++++++++++++++++++++++++++ helpers/contracts-helpers.ts | 404 +------------------------------ 2 files changed, 356 insertions(+), 396 deletions(-) create mode 100644 helpers/contracts-deployments.ts diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts new file mode 100644 index 00000000..4d2a8f62 --- /dev/null +++ b/helpers/contracts-deployments.ts @@ -0,0 +1,348 @@ +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, getGenericLogic} from './contracts-getters'; +import {ZERO_ADDRESS} from './constants'; +import { + AaveProtocolTestHelpersFactory, + ATokenFactory, + ChainlinkProxyPriceProviderFactory, + DefaultReserveInterestRateStrategyFactory, + GenericLogicFactory, + InitializableAdminUpgradeabilityProxyFactory, + LendingPoolAddressesProviderFactory, + LendingPoolAddressesProviderRegistryFactory, + LendingPoolCollateralManagerFactory, + LendingPoolConfiguratorFactory, + LendingPoolFactory, + LendingPoolLibraryAddresses, + LendingRateOracleFactory, + MintableErc20Factory, + MockAggregatorFactory, + MockFlashLoanReceiverFactory, + MockSwapAdapterFactory, + PriceOracleFactory, + ReserveLogicFactory, + StableDebtTokenFactory, + VariableDebtTokenFactory, + WalletBalanceProviderFactory, +} from '../types'; +import {withSaveAndVerify, registerContractInJsonDb, linkBytecode} from './contracts-helpers'; + +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 (verify?: boolean) => + withSaveAndVerify( + await new GenericLogicFactory(await getFirstSigner()).deploy(), + 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 => { + const reserveLogic = await deployReserveLogicLibrary(verify); + const genericLogic = await deployGenericLogic(verify); + const validationLogic = await deployValidationLogic(reserveLogic, genericLogic, verify); + + // Hardcoded solidity placeholders, if any library changes path this will fail. + // Placeholder can be calculated via solidity keccak, but the LendingPoolLibraryAddresses Type seems to + // require a hardcoded string. + // + // how-to: PLACEHOLDER = solidityKeccak256(['string'], `${libPath}:${libName}`).slice(2, 36) + // '__$PLACEHOLDER$__' + // or grab placeholdes from LendingPoolLibraryAddresses at Typechain generation. + return { + ['__$5201a97c05ba6aa659e2f36a933dd51801$__']: reserveLogic.address, + ['__$d3b4366daeb9cadc7528af6145b50b2183$__']: genericLogic.address, + ['__$4c26be947d349222af871a3168b3fe584b$__']: validationLogic.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) => { + const genericLogic = await getGenericLogic(); + const libraries = { + // See deployAaveLibraries() function + ['__$d3b4366daeb9cadc7528af6145b50b2183$__']: genericLogic.address, + }; + + return withSaveAndVerify( + await new LendingPoolCollateralManagerFactory(libraries, 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 deployMockSwapAdapter = async (addressesProvider: tEthereumAddress) => + await new MockSwapAdapterFactory(await getFirstSigner()).deploy(addressesProvider); + +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 => + 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: [string, string, tEthereumAddress, tEthereumAddress, tEthereumAddress], + verify: boolean +) => + withSaveAndVerify( + await new StableDebtTokenFactory(await getFirstSigner()).deploy(...args), + eContractid.StableDebtToken, + args, + verify + ); + +export const deployVariableDebtToken = async ( + args: [string, string, tEthereumAddress, tEthereumAddress, 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]; + withSaveAndVerify( + await new ATokenFactory(await getFirstSigner()).deploy(...args), + eContractid.VariableDebtToken, + 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 = (protoConfigData)[tokenSymbol]; + + if (!configData) { + configData = (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].reserveDecimals || + defaultDecimals.toString(), + ], + verify + ); + await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); + } + return tokens; +}; diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index deef66e1..1926ef44 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -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} from './misc-utils'; import { tEthereumAddress, @@ -9,55 +11,13 @@ import { AavePools, iParamsPerNetwork, iParamsPerPool, - TokenContractId, - iMultiPoolsAssets, - IReserveParams, - PoolConfiguration, } from './types'; - import {MintableErc20 as MintableERC20} from '../types/MintableErc20'; -import {readArtifact} from '@nomiclabs/buidler/plugins'; import {Artifact} from '@nomiclabs/buidler/types'; -import {DefaultReserveInterestRateStrategy} from '../types/DefaultReserveInterestRateStrategy'; -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 {StableDebtToken} from '../types/StableDebtToken'; -import {VariableDebtToken} from '../types/VariableDebtToken'; -import {MockContract} from 'ethereum-waffle'; -import {getReservesConfigByPool} from './configuration'; import {verifyContract} from './etherscan-verification'; -import {getFirstSigner, getGenericLogic} from './contracts-getters'; -const { - ProtocolGlobalParams: {UsdAddress}, -} = CommonsConfig; +import {getIErc20Detailed} from './contracts-getters'; export type MockTokenMap = {[symbol: string]: MintableERC20}; -import {ZERO_ADDRESS} from './constants'; -import {MockSwapAdapter} from '../types/MockSwapAdapter'; -import {signTypedData_v4, TypedData} from 'eth-sig-util'; -import {fromRpcSig, ECDSASignature} from 'ethereumjs-util'; -import {getIErc20Detailed} from './contracts-getters'; -import { - ChainlinkProxyPriceProviderFactory, - GenericLogicFactory, - InitializableAdminUpgradeabilityProxyFactory, - LendingPoolAddressesProviderFactory, - LendingPoolAddressesProviderRegistryFactory, - LendingPoolCollateralManagerFactory, - LendingPoolConfiguratorFactory, - LendingPoolFactory, - LendingPoolLibraryAddresses, - LendingRateOracleFactory, - MockAggregatorFactory, - MockFlashLoanReceiverFactory, - MockSwapAdapterFactory, - PriceOracleFactory, - ReserveLogicFactory, - WalletBalanceProviderFactory, -} from '../types'; export const registerContractInJsonDb = async (contractId: string, contractInstance: Contract) => { const currentNetwork = BRE.network.name; @@ -113,12 +73,12 @@ export const deployContract = async ( return contract; }; -export const withSaveAndVerify = async ( - instance: Contract, +export const withSaveAndVerify = async ( + instance: ContractType, id: string, args: (string | string[])[], verify?: boolean -) => { +): Promise => { await registerContractInJsonDb(id, instance); if (verify) { await verifyContract(id, instance.address, args); @@ -131,300 +91,7 @@ export const getContract = async ( address: string ): Promise => (await BRE.ethers.getContractAt(contractName, address)) as ContractType; -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 (verify?: boolean) => - withSaveAndVerify( - await new GenericLogicFactory(await getFirstSigner()).deploy(), - 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 => { - const reserveLogic = await deployReserveLogicLibrary(verify); - const genericLogic = await deployGenericLogic(verify); - const validationLogic = await deployValidationLogic(reserveLogic, genericLogic, verify); - - // Hardcoded solidity placeholders, if any library changes path this will fail. - // Placeholder can be calculated via solidity keccak, but the LendingPoolLibraryAddresses Type seems to - // require a hardcoded string. - // - // how-to: PLACEHOLDER = solidityKeccak256(['string'], `${libPath}:${libName}`).slice(2, 36) - // '__$PLACEHOLDER$__' - // or grab placeholdes from LendingPoolLibraryAddresses at Typechain generation. - return { - ['__$5201a97c05ba6aa659e2f36a933dd51801$__']: reserveLogic.address, - ['__$d3b4366daeb9cadc7528af6145b50b2183$__']: genericLogic.address, - ['__$4c26be947d349222af871a3168b3fe584b$__']: validationLogic.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) => { - const genericLogic = await getGenericLogic(); - const libraries = { - // See deployAaveLibraries() function - ['__$d3b4366daeb9cadc7528af6145b50b2183$__']: genericLogic.address, - }; - - return withSaveAndVerify( - await new LendingPoolCollateralManagerFactory(libraries, 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 deployMockSwapAdapter = async (addressesProvider: tEthereumAddress) => - await new MockSwapAdapterFactory(await getFirstSigner()).deploy(addressesProvider); - -export const deployAaveProtocolTestHelpers = async ( - addressesProvider: tEthereumAddress, - verify?: boolean -) => { - const args = [addressesProvider]; - const instance = await deployContract( - 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(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(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(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(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(id, args); - - if (verify) { - await verifyContract(id, instance.address, args); - } - return instance; -}; - -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)) { @@ -493,61 +160,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 = (protoConfigData)[tokenSymbol]; - - if (!configData) { - configData = (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].reserveDecimals) || - defaultDecimals, - ]); - await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]); - - if (verify) { - await verifyContract(eContractid.MintableERC20, tokens[tokenSymbol].address, []); - } - } - return tokens; -}; - export const buildPermitParams = ( chainId: number, token: tEthereumAddress, From e0627ce66bbc1af5ea714d30752ce6bf935138c0 Mon Sep 17 00:00:00 2001 From: David Racero Date: Fri, 16 Oct 2020 11:27:09 +0200 Subject: [PATCH 04/33] Added correct library placheholder hashes. Fix imports. --- helpers/contracts-deployments.ts | 29 ++++++++++++-------- helpers/contracts-getters.ts | 14 ++-------- helpers/init-helpers.ts | 11 ++++---- helpers/oracles-helpers.ts | 4 +-- tasks/dev/1_mock_tokens.ts | 2 +- tasks/dev/2_address_provider_registry.ts | 2 +- tasks/dev/3_lending_pool.ts | 4 +-- tasks/dev/4_oracles.ts | 2 +- tasks/dev/5_initialize.ts | 11 +++++--- tasks/full/1_address_provider_registry.ts | 4 +-- tasks/full/2_lending_pool.ts | 4 +-- tasks/full/3_oracles.ts | 5 ++-- tasks/full/5_initialize.ts | 14 ++++++---- test/__setup.spec.ts | 27 ++++++++---------- test/helpers/actions.ts | 1 - test/helpers/make-suite.ts | 1 - test/helpers/utils/calculations.ts | 1 - test/lending-pool-addresses-provider.spec.ts | 2 +- 18 files changed, 66 insertions(+), 72 deletions(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 4d2a8f62..717bd1ca 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -15,7 +15,7 @@ import {MintableErc20 as MintableERC20} from '../types/MintableErc20'; import {readArtifact} from '@nomiclabs/buidler/plugins'; import {MockContract} from 'ethereum-waffle'; import {getReservesConfigByPool} from './configuration'; -import {getFirstSigner, getGenericLogic} from './contracts-getters'; +import {getFirstSigner, getReserveLogic} from './contracts-getters'; import {ZERO_ADDRESS} from './constants'; import { AaveProtocolTestHelpersFactory, @@ -115,17 +115,22 @@ export const deployAaveLibraries = async ( const genericLogic = await deployGenericLogic(verify); const validationLogic = await deployValidationLogic(reserveLogic, genericLogic, verify); + console.log('generic logic address LEND POOL', genericLogic.address); // Hardcoded solidity placeholders, if any library changes path this will fail. - // Placeholder can be calculated via solidity keccak, but the LendingPoolLibraryAddresses Type seems to + // The '__$PLACEHOLDER$__ can be calculated via solidity keccak, but the LendingPoolLibraryAddresses Type seems to // require a hardcoded string. // - // how-to: PLACEHOLDER = solidityKeccak256(['string'], `${libPath}:${libName}`).slice(2, 36) - // '__$PLACEHOLDER$__' + // 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$__']: reserveLogic.address, - ['__$d3b4366daeb9cadc7528af6145b50b2183$__']: genericLogic.address, - ['__$4c26be947d349222af871a3168b3fe584b$__']: validationLogic.address, + ['__$5201a97c05ba6aa659e2f36a933dd51801$__']: validationLogic.address, + ['__$d3b4366daeb9cadc7528af6145b50b2183$__']: reserveLogic.address, + ['__$4c26be947d349222af871a3168b3fe584b$__']: genericLogic.address, }; }; @@ -175,10 +180,10 @@ export const deployChainlinkProxyPriceProvider = async ( ); export const deployLendingPoolCollateralManager = async (verify?: boolean) => { - const genericLogic = await getGenericLogic(); + const reservesLogic = await getReserveLogic(); const libraries = { // See deployAaveLibraries() function - ['__$d3b4366daeb9cadc7528af6145b50b2183$__']: genericLogic.address, + ['__$d3b4366daeb9cadc7528af6145b50b2183$__']: reservesLogic.address, }; return withSaveAndVerify( @@ -256,7 +261,7 @@ export const deployDefaultReserveInterestRateStrategy = async ( ); export const deployStableDebtToken = async ( - args: [string, string, tEthereumAddress, tEthereumAddress, tEthereumAddress], + args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], verify: boolean ) => withSaveAndVerify( @@ -267,7 +272,7 @@ export const deployStableDebtToken = async ( ); export const deployVariableDebtToken = async ( - args: [string, string, tEthereumAddress, tEthereumAddress, tEthereumAddress], + args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress], verify: boolean ) => withSaveAndVerify( @@ -295,7 +300,7 @@ export const deployGenericAToken = async ( string, tEthereumAddress ] = [poolAddress, underlyingAssetAddress, ZERO_ADDRESS, name, symbol, incentivesController]; - withSaveAndVerify( + return withSaveAndVerify( await new ATokenFactory(await getFirstSigner()).deploy(...args), eContractid.VariableDebtToken, args, diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index 5ab75f07..880c878d 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -196,24 +196,16 @@ export const getLendingPoolAddressesProviderRegistry = async (address?: tEthereu await getFirstSigner() ); -export const getReserveLogicLibrary = async (address?: tEthereumAddress) => +export const getReserveLogic = async (address?: tEthereumAddress) => await ReserveLogicFactory.connect( address || - ( - await getDb() - .get(`${eContractid.LendingPoolAddressesProviderRegistry}.${BRE.network.name}`) - .value() - ).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.LendingPoolAddressesProviderRegistry}.${BRE.network.name}`) - .value() - ).address, + (await getDb().get(`${eContractid.GenericLogic}.${BRE.network.name}`).value()).address, await getFirstSigner() ); diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index a2fc3099..d254fc43 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -8,7 +8,8 @@ import { deployStableDebtToken, deployVariableDebtToken, deployGenericAToken, -} from './contracts-helpers'; +} from './contracts-deployments'; +import {getEthersSigners} from './contracts-helpers'; export const enableReservesToBorrow = async ( reservesParams: iMultiPoolsAssets, @@ -151,10 +152,10 @@ export const initReserves = async ( 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}`, - tokenAddress, - lendingPool.address, incentivesController, ], verify @@ -163,10 +164,10 @@ export const initReserves = async ( 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}`, - tokenAddress, - lendingPool.address, incentivesController, ], verify diff --git a/helpers/oracles-helpers.ts b/helpers/oracles-helpers.ts index f87f54b3..f6997f8a 100644 --- a/helpers/oracles-helpers.ts +++ b/helpers/oracles-helpers.ts @@ -11,7 +11,7 @@ import { import {LendingRateOracle} from '../types/LendingRateOracle'; import {PriceOracle} from '../types/PriceOracle'; import {MockAggregator} from '../types/MockAggregator'; -import {deployMockAggregator, getContract, MockTokenMap} from './contracts-helpers'; +import {deployMockAggregator} from './contracts-deployments'; import {waitForTx} from './misc-utils'; import {verifyContract} from './etherscan-verification'; @@ -47,9 +47,7 @@ export const setInitialAssetPricesInOracle = async ( const [, assetAddress] = (Object.entries(assetsAddresses) as [string, string][])[ assetAddressIndex ]; - console.log('PRIOR'); await waitForTx(await priceOracleInstance.setAssetPrice(assetAddress, price)); - console.log('AFTA'); } }; diff --git a/tasks/dev/1_mock_tokens.ts b/tasks/dev/1_mock_tokens.ts index 617071ce..efa3ca04 100644 --- a/tasks/dev/1_mock_tokens.ts +++ b/tasks/dev/1_mock_tokens.ts @@ -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) => { diff --git a/tasks/dev/2_address_provider_registry.ts b/tasks/dev/2_address_provider_registry.ts index 078b56c5..5886774b 100644 --- a/tasks/dev/2_address_provider_registry.ts +++ b/tasks/dev/2_address_provider_registry.ts @@ -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( diff --git a/tasks/dev/3_lending_pool.ts b/tasks/dev/3_lending_pool.ts index 82459557..cc4bce81 100644 --- a/tasks/dev/3_lending_pool.ts +++ b/tasks/dev/3_lending_pool.ts @@ -1,9 +1,8 @@ import {task} from '@nomiclabs/buidler/config'; import { deployLendingPool, - insertContractAddressInDb, deployLendingPoolConfigurator, -} from '../../helpers/contracts-helpers'; +} from '../../helpers/contracts-deployments'; import {eContractid} from '../../helpers/types'; import {waitForTx} from '../../helpers/misc-utils'; import { @@ -11,6 +10,7 @@ import { 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') diff --git a/tasks/dev/4_oracles.ts b/tasks/dev/4_oracles.ts index 5ab756d9..415f6884 100644 --- a/tasks/dev/4_oracles.ts +++ b/tasks/dev/4_oracles.ts @@ -3,7 +3,7 @@ import { deployPriceOracle, deployChainlinkProxyPriceProvider, deployLendingRateOracle, -} from '../../helpers/contracts-helpers'; +} from '../../helpers/contracts-deployments'; import { setInitialAssetPricesInOracle, diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index e504decd..28c59bbf 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -1,17 +1,19 @@ import {task} from '@nomiclabs/buidler/config'; import { - initReserves, deployLendingPoolCollateralManager, - insertContractAddressInDb, deployMockFlashLoanReceiver, deployWalletBalancerProvider, deployAaveProtocolTestHelpers, -} 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 { + enableReservesToBorrow, + enableReservesAsCollateral, + initReserves, +} from '../../helpers/init-helpers'; import {getAllTokenAddresses} from '../../helpers/mock-helpers'; import {ZERO_ADDRESS} from '../../helpers/constants'; import { @@ -20,6 +22,7 @@ import { 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') diff --git a/tasks/full/1_address_provider_registry.ts b/tasks/full/1_address_provider_registry.ts index 11195e66..24534901 100644 --- a/tasks/full/1_address_provider_registry.ts +++ b/tasks/full/1_address_provider_registry.ts @@ -1,9 +1,9 @@ import {task} from '@nomiclabs/buidler/config'; +import {getParamPerNetwork} from '../../helpers/contracts-helpers'; import { deployLendingPoolAddressesProvider, deployLendingPoolAddressesProviderRegistry, - getParamPerNetwork, -} 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'; diff --git a/tasks/full/2_lending_pool.ts b/tasks/full/2_lending_pool.ts index 5c3fb7f9..cd498a0b 100644 --- a/tasks/full/2_lending_pool.ts +++ b/tasks/full/2_lending_pool.ts @@ -1,9 +1,9 @@ import {task} from '@nomiclabs/buidler/config'; +import {insertContractAddressInDb} from '../../helpers/contracts-helpers'; import { deployLendingPool, - insertContractAddressInDb, deployLendingPoolConfigurator, -} from '../../helpers/contracts-helpers'; +} from '../../helpers/contracts-deployments'; import {eContractid} from '../../helpers/types'; import {waitForTx} from '../../helpers/misc-utils'; import { diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index 9d640448..853330f2 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -1,10 +1,9 @@ import {task} from '@nomiclabs/buidler/config'; +import {getParamPerNetwork} from '../../helpers/contracts-helpers'; import { deployChainlinkProxyPriceProvider, deployLendingRateOracle, - getParamPerNetwork, -} from '../../helpers/contracts-helpers'; - +} from '../../helpers/contracts-deployments'; import {setInitialMarketRatesInRatesOracle} from '../../helpers/oracles-helpers'; import {ICommonConfiguration, eEthereumNetwork, SymbolMap} from '../../helpers/types'; import {waitForTx, filterMapBy} from '../../helpers/misc-utils'; diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 1c54fd69..fe2c5c42 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -1,16 +1,18 @@ import {task} from '@nomiclabs/buidler/config'; +import {getParamPerNetwork} from '../../helpers/contracts-helpers'; import { - initReserves, deployLendingPoolCollateralManager, deployWalletBalancerProvider, deployAaveProtocolTestHelpers, - getParamPerNetwork, -} from '../../helpers/contracts-helpers'; +} from '../../helpers/contracts-deployments'; import {loadPoolConfig, ConfigNames} from '../../helpers/configuration'; - -import {AavePools, eContractid, eEthereumNetwork, ICommonConfiguration} from '../../helpers/types'; +import {AavePools, eEthereumNetwork, ICommonConfiguration} from '../../helpers/types'; import {waitForTx} from '../../helpers/misc-utils'; -import {enableReservesToBorrow, enableReservesAsCollateral} from '../../helpers/init-helpers'; +import { + enableReservesToBorrow, + enableReservesAsCollateral, + initReserves, +} from '../../helpers/init-helpers'; import {ZERO_ADDRESS} from '../../helpers/constants'; import {exit} from 'process'; import { diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index 6a02b940..a6c20849 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -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, @@ -11,20 +16,15 @@ import { deployLendingPoolCollateralManager, deployMockFlashLoanReceiver, deployWalletBalancerProvider, - insertContractAddressInDb, deployAaveProtocolTestHelpers, - getEthersSigners, - registerContractInJsonDb, - initReserves, deployMockSwapAdapter, deployLendingRateOracle, -} from '../helpers/contracts-helpers'; +} 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, @@ -32,7 +32,11 @@ import { deployAllMockAggregators, } from '../helpers/oracles-helpers'; import {waitForTx} from '../helpers/misc-utils'; -import {enableReservesToBorrow, enableReservesAsCollateral} from '../helpers/init-helpers'; +import { + enableReservesToBorrow, + enableReservesAsCollateral, + initReserves, +} from '../helpers/init-helpers'; import {AaveConfig} from '../config/aave'; import {ZERO_ADDRESS} from '../helpers/constants'; import { @@ -95,14 +99,9 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { 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(); @@ -112,6 +111,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy( await addressesProvider.getLendingPoolConfigurator() ); + console.log('proxy address', lendingPoolConfiguratorProxy.address); await insertContractAddressInDb( eContractid.LendingPoolConfigurator, lendingPoolConfiguratorProxy.address @@ -152,10 +152,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { fallbackOracle ); - console.log('setted prices'); - console.log('prior mocks'); const mockAggregators = await deployAllMockAggregators(MOCK_CHAINLINK_AGGREGATORS_PRICES); - console.log('aftahlocks'); const allTokenAddresses = Object.entries(mockTokens).reduce( (accum: {[tokenSymbol: string]: tEthereumAddress}, [tokenSymbol, tokenContract]) => ({ diff --git a/test/helpers/actions.ts b/test/helpers/actions.ts index 0ab80a21..422b0455 100644 --- a/test/helpers/actions.ts +++ b/test/helpers/actions.ts @@ -28,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; diff --git a/test/helpers/make-suite.ts b/test/helpers/make-suite.ts index 29b1f546..d11278ea 100644 --- a/test/helpers/make-suite.ts +++ b/test/helpers/make-suite.ts @@ -27,7 +27,6 @@ import {LendingPoolAddressesProvider} from '../../types/LendingPoolAddressesProv import {MockSwapAdapter} from '../../types/MockSwapAdapter'; import {LendingPoolAddressesProviderRegistry} from '../../types/LendingPoolAddressesProviderRegistry'; import {getEthersSigners} from '../../helpers/contracts-helpers'; -import {AaveProtocolTestHelpersFactory} from '../../types'; chai.use(bignumberChai()); chai.use(almostEqual()); diff --git a/test/helpers/utils/calculations.ts b/test/helpers/utils/calculations.ts index 46623a62..894f3373 100644 --- a/test/helpers/utils/calculations.ts +++ b/test/helpers/utils/calculations.ts @@ -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'; diff --git a/test/lending-pool-addresses-provider.spec.ts b/test/lending-pool-addresses-provider.spec.ts index ed283c46..4858531a 100644 --- a/test/lending-pool-addresses-provider.spec.ts +++ b/test/lending-pool-addresses-provider.spec.ts @@ -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; From 60c93a4d7312ae11bbb3b3961c6fb21161c14419 Mon Sep 17 00:00:00 2001 From: David Racero Date: Fri, 16 Oct 2020 12:07:35 +0200 Subject: [PATCH 05/33] Remove debug console.logs --- helpers/contracts-deployments.ts | 1 - tasks/full/5_initialize.ts | 5 ----- test/helpers/make-suite.ts | 2 -- 3 files changed, 8 deletions(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 717bd1ca..07ee9947 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -115,7 +115,6 @@ export const deployAaveLibraries = async ( const genericLogic = await deployGenericLogic(verify); const validationLogic = await deployValidationLogic(reserveLogic, genericLogic, verify); - console.log('generic logic address LEND POOL', genericLogic.address); // 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. diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index fe2c5c42..6423b09d 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -40,7 +40,6 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const testHelpers = await deployAaveProtocolTestHelpers(addressesProvider.address, verify); - console.log('init reserves'); await initReserves( ReservesConfig, reserveAssets, @@ -52,14 +51,12 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') ZERO_ADDRESS, verify ); - console.log('enable reserves'); await enableReservesToBorrow( ReservesConfig, reserveAssets, testHelpers, lendingPoolConfiguratorProxy ); - console.log('enable reserves as collateral'); await enableReservesAsCollateral( ReservesConfig, reserveAssets, @@ -67,13 +64,11 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') lendingPoolConfiguratorProxy ); - 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); diff --git a/test/helpers/make-suite.ts b/test/helpers/make-suite.ts index d11278ea..f93e4e79 100644 --- a/test/helpers/make-suite.ts +++ b/test/helpers/make-suite.ts @@ -92,10 +92,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(); From 3b2b843b7b8fc8139ff943c752c9cbe8f4f86fe8 Mon Sep 17 00:00:00 2001 From: David Racero Date: Thu, 22 Oct 2020 18:14:56 +0200 Subject: [PATCH 06/33] Fixes typings errors. --- helpers/contracts-deployments.ts | 85 ++---------------------------- test/__setup.spec.ts | 1 - test/atoken-permit.spec.ts | 8 +-- test/repay-with-collateral.spec.ts | 3 ++ 4 files changed, 7 insertions(+), 90 deletions(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 2fddf680..7b8a537f 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -15,14 +15,13 @@ import {MintableErc20 as MintableERC20} from '../types/MintableErc20'; import {readArtifact} from '@nomiclabs/buidler/plugins'; import {MockContract} from 'ethereum-waffle'; import {getReservesConfigByPool} from './configuration'; -import {getFirstSigner, getReserveLogic} from './contracts-getters'; +import {getFirstSigner} from './contracts-getters'; import {ZERO_ADDRESS} from './constants'; import { AaveProtocolTestHelpersFactory, ATokenFactory, ChainlinkProxyPriceProviderFactory, DefaultReserveInterestRateStrategyFactory, - GenericLogicFactory, InitializableAdminUpgradeabilityProxyFactory, LendingPoolAddressesProviderFactory, LendingPoolAddressesProviderRegistryFactory, @@ -42,9 +41,6 @@ import { WalletBalanceProviderFactory, } from '../types'; import {withSaveAndVerify, registerContractInJsonDb, linkBytecode} from './contracts-helpers'; -import {verifyContract} from './etherscan-verification'; -import {LendingPool} from '../types/LendingPool'; -import {Artifact} from '@nomiclabs/buidler/types'; export const deployLendingPoolAddressesProvider = async (verify?: boolean) => withSaveAndVerify( @@ -147,7 +143,7 @@ export const deployAaveLibraries = async ( }; }; -export const deployLendingPoolWithFactory = async (verify?: boolean) => { +export const deployLendingPool = async (verify?: boolean) => { const libraries = await deployAaveLibraries(verify); return withSaveAndVerify( await new LendingPoolFactory(libraries, await getFirstSigner()).deploy(), @@ -157,74 +153,6 @@ export const deployLendingPoolWithFactory = async (verify?: boolean) => { ); }; -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(); - const instance = (await lendingPool.deployed()) as LendingPool; - if (verify) { - await verifyContract(eContractid.LendingPool, instance.address, []); - } - return instance; -}; - export const deployPriceOracle = async (verify?: boolean) => withSaveAndVerify( await new PriceOracleFactory(await getFirstSigner()).deploy(), @@ -261,15 +189,8 @@ export const deployChainlinkProxyPriceProvider = async ( ); export const deployLendingPoolCollateralManager = async (verify?: boolean) => { - const reservesLogic = await getReserveLogic(); - console.log('ADDRESS RESERVELOGIC', reservesLogic.address); - const libraries = { - // See deployAaveLibraries() function - ['__$d3b4366daeb9cadc7528af6145b50b2183$__']: reservesLogic.address, - }; - return withSaveAndVerify( - await new LendingPoolCollateralManagerFactory(libraries, await getFirstSigner()).deploy(), + await new LendingPoolCollateralManagerFactory(await getFirstSigner()).deploy(), eContractid.LendingPoolCollateralManager, [], verify diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index d0b85e3f..a674b659 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -111,7 +111,6 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy( await addressesProvider.getLendingPoolConfigurator() ); - console.log('proxy address', lendingPoolConfiguratorProxy.address); await insertContractAddressInDb( eContractid.LendingPoolConfigurator, lendingPoolConfiguratorProxy.address diff --git a/test/atoken-permit.spec.ts b/test/atoken-permit.spec.ts index 5f506758..44c90008 100644 --- a/test/atoken-permit.spec.ts +++ b/test/atoken-permit.spec.ts @@ -32,17 +32,11 @@ makeSuite('AToken: Permit', (testEnv: TestEnv) => { }); it('Get aDAI for tests', async () => { - const {dai, pool, deployer, addressesProvider} = testEnv; - const addre = await addressesProvider.getLendingPool(); - console.log('pool', pool.address, addre); + const {dai, pool, deployer} = testEnv; await dai.mint(parseEther('20000')); await dai.approve(pool.address, parseEther('20000')); - const some = await pool.getReserveData(dai.address); - const aa = await pool.getReservesList(); - console.log('some', some); - console.log('aa', aa); await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0); }); diff --git a/test/repay-with-collateral.spec.ts b/test/repay-with-collateral.spec.ts index 282cddb3..cb8e9a09 100644 --- a/test/repay-with-collateral.spec.ts +++ b/test/repay-with-collateral.spec.ts @@ -1,3 +1,4 @@ +/* import {TestEnv, makeSuite} from './helpers/make-suite'; import {APPROVAL_AMOUNT_LENDING_POOL} from '../helpers/constants'; import {ethers} from 'ethers'; @@ -680,3 +681,5 @@ makeSuite('LendingPool. repayWithCollateral()', (testEnv: TestEnv) => { expect(wethUserDataAfter.usageAsCollateralEnabled).to.be.false; }); }); + +*/ From 64df1eeb361eda85fa2c0b79aaad2ce658d7131a Mon Sep 17 00:00:00 2001 From: David Racero Date: Thu, 22 Oct 2020 18:27:23 +0200 Subject: [PATCH 07/33] Removed mock swap --- deployed-contracts.json | 22 ++++++---------------- helpers/contracts-deployments.ts | 4 ---- helpers/contracts-getters.ts | 8 -------- helpers/types.ts | 1 - test/__setup.spec.ts | 4 ---- test/helpers/make-suite.ts | 6 ------ test/pausable-functions.spec.ts | 2 +- 7 files changed, 7 insertions(+), 40 deletions(-) diff --git a/deployed-contracts.json b/deployed-contracts.json index c51ca112..64d6eb71 100644 --- a/deployed-contracts.json +++ b/deployed-contracts.json @@ -86,7 +86,8 @@ }, "LendingPool": { "buidlerevm": { - "address": "0xD9273d497eDBC967F39d419461CfcF382a0A822e" + "address": "0xBEF0d4b9c089a5883741fC14cbA352055f35DDA2", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { "address": "0x3EE716e38f21e5FC16BFDB773db24D63C637A5d8" @@ -235,7 +236,7 @@ }, "WalletBalanceProvider": { "buidlerevm": { - "address": "0xd4e934C2749CA8C1618659D02E7B28B074bf4df7", + "address": "0x93bB79570dFECC052e36E25cE10793A139e75f1b", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -694,17 +695,6 @@ "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, - "MockSwapAdapter": { - "buidlerevm": { - "address": "0x93bB79570dFECC052e36E25cE10793A139e75f1b" - }, - "coverage": { - "address": "0xBEF0d4b9c089a5883741fC14cbA352055f35DDA2" - }, - "localhost": { - "address": "0x48FAde2E719B770E1783d03466dAEe98b5183538" - } - }, "MockFlashRepayAdapter": { "buidlerevm": { "address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10" @@ -717,19 +707,19 @@ }, "ReserveLogic": { "buidlerevm": { - "address": "0xFAe0fd738dAbc8a0426F47437322b6d026A9FD95", + "address": "0x63387deC8C4a0F17Cf0C27Ea3476F03F6a45d3AE", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, "GenericLogic": { "buidlerevm": { - "address": "0x6082731fdAba4761277Fb31299ebC782AD3bCf24", + "address": "0x8280D40C9E9F04229D2435EAad6e0011309ce81B", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, "ValidationLogic": { "buidlerevm": { - "address": "0x8456161947DFc1fC159A0B26c025cD2b4bba0c3e", + "address": "0x2B681757d757fbB80cc51c6094cEF5eE75bF55aA", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 7b8a537f..dc10288d 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -33,7 +33,6 @@ import { MintableErc20Factory, MockAggregatorFactory, MockFlashLoanReceiverFactory, - MockSwapAdapterFactory, PriceOracleFactory, ReserveLogicFactory, StableDebtTokenFactory, @@ -227,9 +226,6 @@ export const deployWalletBalancerProvider = async ( verify ); -export const deployMockSwapAdapter = async (addressesProvider: tEthereumAddress) => - await new MockSwapAdapterFactory(await getFirstSigner()).deploy(addressesProvider); - export const deployAaveProtocolTestHelpers = async ( addressesProvider: tEthereumAddress, verify?: boolean diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index 880c878d..231b87e0 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -10,7 +10,6 @@ import { LendingRateOracleFactory, MintableErc20Factory, MockFlashLoanReceiverFactory, - MockSwapAdapterFactory, PriceOracleFactory, ReserveLogicFactory, StableDebtTokenFactory, @@ -115,13 +114,6 @@ export const getMockFlashLoanReceiver = async (address?: tEthereumAddress) => await getFirstSigner() ); -export const getMockSwapAdapter = async (address?: tEthereumAddress) => - await MockSwapAdapterFactory.connect( - address || - (await getDb().get(`${eContractid.MockSwapAdapter}.${BRE.network.name}`).value()).address, - await getFirstSigner() - ); - export const getLendingRateOracle = async (address?: tEthereumAddress) => await LendingRateOracleFactory.connect( address || diff --git a/helpers/types.ts b/helpers/types.ts index 26644896..29cf3a77 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -44,7 +44,6 @@ export enum eContractid { LendingPoolCollateralManager = 'LendingPoolCollateralManager', InitializableAdminUpgradeabilityProxy = 'InitializableAdminUpgradeabilityProxy', MockFlashLoanReceiver = 'MockFlashLoanReceiver', - MockSwapAdapter = 'MockSwapAdapter', WalletBalanceProvider = 'WalletBalanceProvider', AToken = 'AToken', MockAToken = 'MockAToken', diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index a674b659..3b84cb94 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -17,7 +17,6 @@ import { deployMockFlashLoanReceiver, deployWalletBalancerProvider, deployAaveProtocolTestHelpers, - deployMockSwapAdapter, deployLendingRateOracle, } from '../helpers/contracts-deployments'; import {Signer} from 'ethers'; @@ -239,9 +238,6 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const mockFlashLoanReceiver = await deployMockFlashLoanReceiver(addressesProvider.address); await insertContractAddressInDb(eContractid.MockFlashLoanReceiver, mockFlashLoanReceiver.address); - const mockSwapAdapter = await deployMockSwapAdapter(addressesProvider.address); - await insertContractAddressInDb(eContractid.MockSwapAdapter, mockSwapAdapter.address); - await deployWalletBalancerProvider(addressesProvider.address); console.log('END'); diff --git a/test/helpers/make-suite.ts b/test/helpers/make-suite.ts index f93e4e79..11e8c9f8 100644 --- a/test/helpers/make-suite.ts +++ b/test/helpers/make-suite.ts @@ -8,7 +8,6 @@ import { getMintableErc20, getLendingPoolConfiguratorProxy, getPriceOracle, - getMockSwapAdapter, getLendingPoolAddressesProviderRegistry, } from '../../helpers/contracts-getters'; import {tEthereumAddress} from '../../helpers/types'; @@ -24,7 +23,6 @@ import bignumberChai from 'chai-bignumber'; import {almostEqual} from './almost-equal'; import {PriceOracle} from '../../types/PriceOracle'; import {LendingPoolAddressesProvider} from '../../types/LendingPoolAddressesProvider'; -import {MockSwapAdapter} from '../../types/MockSwapAdapter'; import {LendingPoolAddressesProviderRegistry} from '../../types/LendingPoolAddressesProviderRegistry'; import {getEthersSigners} from '../../helpers/contracts-helpers'; chai.use(bignumberChai()); @@ -48,7 +46,6 @@ export interface TestEnv { usdc: MintableERC20; lend: MintableERC20; addressesProvider: LendingPoolAddressesProvider; - mockSwapAdapter: MockSwapAdapter; registry: LendingPoolAddressesProviderRegistry; } @@ -73,7 +70,6 @@ const testEnv: TestEnv = { usdc: {} as MintableERC20, lend: {} as MintableERC20, addressesProvider: {} as LendingPoolAddressesProvider, - mockSwapAdapter: {} as MockSwapAdapter, registry: {} as LendingPoolAddressesProviderRegistry, } as TestEnv; @@ -132,8 +128,6 @@ export async function initializeMakeSuite() { testEnv.usdc = await getMintableErc20(usdcAddress); testEnv.lend = await getMintableErc20(lendAddress); testEnv.weth = await getMintableErc20(wethAddress); - - testEnv.mockSwapAdapter = await getMockSwapAdapter(); } export function makeSuite(name: string, tests: (testEnv: TestEnv) => void) { diff --git a/test/pausable-functions.spec.ts b/test/pausable-functions.spec.ts index 51db0398..62394969 100644 --- a/test/pausable-functions.spec.ts +++ b/test/pausable-functions.spec.ts @@ -276,7 +276,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { }); it('SwapBorrowRateMode', async () => { - const {pool, weth, dai, usdc, users, configurator, mockSwapAdapter} = testEnv; + const {pool, weth, dai, usdc, users, configurator} = testEnv; const user = users[1]; const amountWETHToDeposit = parseEther('10'); const amountDAIToDeposit = parseEther('120'); From 1c7ce57b2bd28385059887fa6a4c0b46e1def964 Mon Sep 17 00:00:00 2001 From: David Racero Date: Fri, 23 Oct 2020 18:38:27 +0200 Subject: [PATCH 08/33] Aggregated deployments for initialization, atokens and debtTokens --- buidler.config.ts | 2 +- .../deployments/DeployATokensAndRates.sol | 2 +- contracts/deployments/ReserveInitializer.sol | 35 ---- deployed-contracts.json | 38 ++-- helpers/init-helpers.ts | 169 +++++++++++------- helpers/misc-utils.ts | 10 ++ tasks/dev/5_initialize.ts | 16 +- tasks/full/5_initialize.ts | 21 ++- test/__setup.spec.ts | 14 +- test/helpers/make-suite.ts | 9 +- test/{test-init.spec.ts => test-init.ts} | 5 +- 11 files changed, 173 insertions(+), 148 deletions(-) delete mode 100644 contracts/deployments/ReserveInitializer.sol rename test/{test-init.spec.ts => test-init.ts} (98%) diff --git a/buidler.config.ts b/buidler.config.ts index ae6ef7e3..f2ff1604 100644 --- a/buidler.config.ts +++ b/buidler.config.ts @@ -14,7 +14,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 || ''; diff --git a/contracts/deployments/DeployATokensAndRates.sol b/contracts/deployments/DeployATokensAndRates.sol index 3e66802a..78076903 100644 --- a/contracts/deployments/DeployATokensAndRates.sol +++ b/contracts/deployments/DeployATokensAndRates.sol @@ -27,7 +27,7 @@ contract DeployATokensAndRates { } function concat(string memory a, string memory b) internal pure returns (string memory) { - return string(abi.encodePacked(a, ' ', b)); + return string(abi.encodePacked(a, b)); } function initDeployment( diff --git a/contracts/deployments/ReserveInitializer.sol b/contracts/deployments/ReserveInitializer.sol deleted file mode 100644 index d1d85bf4..00000000 --- a/contracts/deployments/ReserveInitializer.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity ^0.6.8; -pragma experimental ABIEncoderV2; - -import {LendingPoolConfigurator} from '../lendingpool/LendingPoolConfigurator.sol'; - -contract ReserveInitializer { - address private poolConfigurator; - - constructor(address _poolConfigurator) public { - poolConfigurator = _poolConfigurator; - } - - 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) - - for (uint256 i = 0; i < tokens.length; i++) { - LendingPoolConfigurator(poolConfigurator).initReserve( - tokens[i], - aTokens[i], - stables[i], - variables[i], - reserveDecimals[i], - strategies[i] - ); - } - } -} diff --git a/deployed-contracts.json b/deployed-contracts.json index 66f1ffe9..9891a3ca 100644 --- a/deployed-contracts.json +++ b/deployed-contracts.json @@ -1,7 +1,7 @@ { "MintableERC20": { "buidlerevm": { - "address": "0xB7d4f04E8dF26d2FEE35D4AeB2A63fEB49451B78", + "address": "0x58F132FBB86E21545A4Bace3C19f1C05d86d7A22", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -15,7 +15,7 @@ }, "LendingPoolAddressesProvider": { "buidlerevm": { - "address": "0xC5f7aC6895DcB76877E71db756433fB0E0478FEB", + "address": "0xa4bcDF64Cdd5451b6ac3743B414124A6299B65FF", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -33,7 +33,7 @@ }, "LendingPoolAddressesProviderRegistry": { "buidlerevm": { - "address": "0x4b2c297ba5be42610994974b9543D56B864CA011", + "address": "0x5A0773Ff307Bf7C71a832dBB5312237fD3437f9F", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -70,7 +70,7 @@ }, "LendingPoolConfigurator": { "buidlerevm": { - "address": "0x891E9f1BbD041265856b486DE4F5A5c5659370b6" + "address": "0x6642B57e4265BAD868C17Fc1d1F4F88DBBA04Aa8" }, "localhost": { "address": "0x9Ec55627757348b322c8dD0865D704649bFa0c7b" @@ -86,7 +86,7 @@ }, "LendingPool": { "buidlerevm": { - "address": "0x08ce4E45cD12Ae467fF24A1fd563321De309B613" + "address": "0xD9273d497eDBC967F39d419461CfcF382a0A822e" }, "localhost": { "address": "0x3EE716e38f21e5FC16BFDB773db24D63C637A5d8" @@ -97,7 +97,7 @@ }, "PriceOracle": { "buidlerevm": { - "address": "0x951d1CE3CE90D719F5BdeCBbFE6EeA9c7bff948E", + "address": "0x0C6c3C47A1f650809B0D1048FDf9603e09473D7E", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -111,7 +111,7 @@ }, "MockAggregator": { "buidlerevm": { - "address": "0xff1B1B810F5DCe853a9b1819DE220D532D1CFeF2", + "address": "0xc11f8E173ee67ffA7BBdD185D2399994AAd23Ec6", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -125,7 +125,7 @@ }, "ChainlinkProxyPriceProvider": { "buidlerevm": { - "address": "0xf55Af78B3f3059fACF166Aa338FFe059A14e75F6", + "address": "0xD662fb7FDC7526C79AA4417d2A4415416e057ec4", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -143,7 +143,7 @@ }, "LendingRateOracle": { "buidlerevm": { - "address": "0xaD3AdbC18E4AD090034A6C74Eda61f4310dce313", + "address": "0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -224,7 +224,7 @@ }, "MockFlashLoanReceiver": { "buidlerevm": { - "address": "0x5Ea694f66BD0CBd08FC7967af01b67Dcef68cC5c" + "address": "0xB8054085AF605D93c32E6B829d3d7eA2A8C84F9A" }, "localhost": { "address": "0x9c91aEaD98b1354C7B0EAfb8ff539d0796c79894" @@ -235,7 +235,7 @@ }, "WalletBalanceProvider": { "buidlerevm": { - "address": "0x93bB79570dFECC052e36E25cE10793A139e75f1b", + "address": "0xA3Ab089388B0C1BA83B3496696242FcA3F8eb9D5", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -571,7 +571,7 @@ }, "AaveProtocolTestHelpers": { "buidlerevm": { - "address": "0xa89E20284Bd638F31b0011D0fC754Fc9d2fa73e3" + "address": "0x93472C0e03215F9c33DA240Eb16703C8244eAa8c" }, "localhost": { "address": "0x987223924D2DD6c6efB601756850f3886ECbceF6" @@ -640,7 +640,7 @@ }, "MockAToken": { "buidlerevm": { - "address": "0x392E5355a0e88Bd394F717227c752670fb3a8020", + "address": "0x2dC17ABe95C889aA4c9474eD45Dd454Ed1Ec1ec1", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -668,7 +668,7 @@ }, "MockStableDebtToken": { "buidlerevm": { - "address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460", + "address": "0x8b949D7E587518A6ad727ef30C5815De4a16A0D7", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -682,7 +682,7 @@ }, "MockVariableDebtToken": { "buidlerevm": { - "address": "0xEBAB67ee3ef604D5c250A53b4b8fcbBC6ec3007C", + "address": "0xCC5F3Be6e695bD0239dFd0efC8E9FFC6E969D29e", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -706,25 +706,25 @@ }, "ReserveLogic": { "buidlerevm": { - "address": "0x285671fF5C8172dE63cF5eA264B2e827aDBC6740", + "address": "0xFAe0fd738dAbc8a0426F47437322b6d026A9FD95", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, "GenericLogic": { "buidlerevm": { - "address": "0xb840b4fe440b5E26e1840cd2D6320FAda1C0ca5d", + "address": "0x6082731fdAba4761277Fb31299ebC782AD3bCf24", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, "ValidationLogic": { "buidlerevm": { - "address": "0x1a432D97211e8b2CD53DF262c8Da0EfeBa6b6b3D", + "address": "0x8456161947DFc1fC159A0B26c025cD2b4bba0c3e", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, "LendingPoolCollateralManager": { "buidlerevm": { - "address": "0xb2B548BE73010C188C083c510d255Aed74843b05", + "address": "0xeB80313502EA077FA9B8E89b45e4a1B236cA17Ea", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } } diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 706f8e58..f88c2620 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -9,10 +9,10 @@ import { deployVariableDebtToken, deployGenericAToken, } from './contracts-deployments'; -import {waitForTx} from './misc-utils'; +import {chunk, waitForTx} from './misc-utils'; import {DeployTokens} from '../types/DeployTokens'; import {ZERO_ADDRESS} from './constants'; -import {getFirstSigner} from './contracts-getters'; +import {getFirstSigner, getLendingPoolAddressesProvider} from './contracts-getters'; import {DeployATokensAndRatesFactory} from '../types/DeployATokensAndRatesFactory'; import {DeployStableAndVariableTokensFactory} from '../types/DeployStableAndVariableTokensFactory'; import {getDefaultSettings} from 'http2'; @@ -233,93 +233,138 @@ export const initReservesByHelper = async ( lendingPoolConfigurator: tEthereumAddress, reservesParams: iMultiPoolsAssets, tokenAddresses: {[symbol: string]: tEthereumAddress}, - helpers: AaveProtocolTestHelpers + helpers: AaveProtocolTestHelpers, + admin: tEthereumAddress, + incentivesController: tEthereumAddress ) => { const stableAndVariableDeployer = await new DeployStableAndVariableTokensFactory( await getFirstSigner() ).deploy(lendingPoolProxy, addressesProvider); - const stableTx = await waitForTx(stableAndVariableDeployer.deployTransaction); - console.log('GAS', stableTx.gasUsed.toString()); - console.log('- Deployed StableAndVariableDeployer'); + await waitForTx(stableAndVariableDeployer.deployTransaction); const atokenAndRatesDeployer = await new DeployATokensAndRatesFactory( await getFirstSigner() ).deploy(lendingPoolProxy, addressesProvider, lendingPoolConfigurator); - const atokenTx = await waitForTx(atokenAndRatesDeployer.deployTransaction); - console.log('GAS', atokenTx.gasUsed.toString()); - console.log('- Deployed ATokenAndRatesDeployer'); - console.log('doing calls'); - 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 - ]; + await waitForTx(atokenAndRatesDeployer.deployTransaction); + const addressProvider = await getLendingPoolAddressesProvider(addressesProvider); - const {isActive: reserveInitialized} = await helpers.getReserveConfigurationData(tokenAddress); + // Set aTokenAndRatesDeployer as temporal admin + await waitForTx(await addressProvider.setAaveAdmin(atokenAndRatesDeployer.address)); - if (reserveInitialized) { - console.log(`Reserve ${assetSymbol} is already active, skipping configuration`); - continue; - } + // CHUNK CONFIGURATION + const tokensChunks = 3; + const initChunks = 6; - const reserveParamIndex = Object.keys(reservesParams).findIndex( - (value) => value === assetSymbol - ); - const [ - , - { + // 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 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 === 'WETH' ? 'ETH' : assetSymbol); + strategyRates.push([ baseVariableBorrowRate, variableRateSlope1, variableRateSlope2, stableRateSlope1, stableRateSlope2, - }, - ] = (Object.entries(reservesParams) as [string, IReserveParams][])[reserveParamIndex]; - assetSymbol = assetSymbol === 'WETH' ? 'ETH' : assetSymbol; + ]); + reservesDecimals.push(reserveDecimals); + } + + // Deploy stable and variable deployers const tx1 = await waitForTx( - await stableAndVariableDeployer.initDeployment([tokenAddress], [assetSymbol], ZERO_ADDRESS, { - gasLimit: 9000000, - }) + await stableAndVariableDeployer.initDeployment(tokens, symbols, incentivesController) ); - console.log('call 1', tx1.gasUsed.toString()); - - const stableTokens: string[] = tx1.events?.map((e) => e.args?.stableToken) || []; - const variableTokens: string[] = tx1.events?.map((e) => e.args?.variableToken) || []; + // Deploy atokens and rate strategies const tx2 = await waitForTx( await atokenAndRatesDeployer.initDeployment( - [tokenAddress], - [assetSymbol], - [ - [ - baseVariableBorrowRate, - variableRateSlope1, - variableRateSlope2, - stableRateSlope1, - stableRateSlope2, - ], - ], - ZERO_ADDRESS + 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) || []; - console.log(aTokens.length, strategies.length, stableTokens.length, variableTokens.length); - console.log('call 2', tx2.gasUsed.toString()); + + deployedStableTokens = [...deployedStableTokens, ...stableTokens]; + deployedVariableTokens = [...deployedVariableTokens, ...variableTokens]; + deployedATokens = [...deployedATokens, ...aTokens]; + deployedRates = [...deployedRates, ...strategies]; + reserveInitDecimals = [...reserveInitDecimals, ...reservesDecimals]; + reserveTokens = [...reserveTokens, ...tokens]; + } + + // 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); + const chunkedRates = chunk(deployedRates, initChunks); + const chunkedDecimals = chunk(reserveInitDecimals, initChunks); + const chunkedSymbols = chunk(Object.keys(tokenAddresses), initChunks); + + console.log(`- Reserves initialization in ${chunkedTokens.length} txs`); + for (let chunkIndex = 0; chunkIndex < chunkedDecimals.length; chunkIndex++) { const tx3 = await waitForTx( await atokenAndRatesDeployer.initReserve( - [tokenAddress], - stableTokens, - variableTokens, - aTokens, - strategies, - [reserveDecimals] + chunkedTokens[chunkIndex], + chunkedStableTokens[chunkIndex], + chunkedVariableTokens[chunkIndex], + chunkedAtokens[chunkIndex], + chunkedRates[chunkIndex], + chunkedDecimals[chunkIndex] ) ); - console.log('call 3', tx3.gasUsed.toString()); + console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`); } + + // Set deployer back as admin + await waitForTx(await addressProvider.setAaveAdmin(admin)); }; diff --git a/helpers/misc-utils.ts b/helpers/misc-utils.ts index b3b29b7f..3df0e7d8 100644 --- a/helpers/misc-utils.ts +++ b/helpers/misc-utils.ts @@ -52,3 +52,13 @@ export const filterMapBy = (raw: {[key: string]: any}, fn: (key: string) => bool obj[key] = raw[key]; return obj; }, {}); + +export const chunk = (arr: Array, chunkSize: number): Array> => { + return arr.reduce( + (prevVal: any, currVal: any, currIndx: number, array: Array) => + !(currIndx % chunkSize) + ? prevVal.concat([array.slice(currIndx, currIndx + chunkSize)]) + : prevVal, + [] + ); +}; diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index 28c59bbf..213ed6cd 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -13,6 +13,7 @@ import { enableReservesToBorrow, enableReservesAsCollateral, initReserves, + initReservesByHelper, } from '../../helpers/init-helpers'; import {getAllTokenAddresses} from '../../helpers/mock-helpers'; import {ZERO_ADDRESS} from '../../helpers/constants'; @@ -44,16 +45,17 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') const reservesParams = getReservesConfigByPool(AavePools.proto); - await initReserves( + const admin = await addressesProvider.getAaveAdmin(); + + await initReservesByHelper( + lendingPoolProxy.address, + addressesProvider.address, + lendingPoolConfiguratorProxy.address, reservesParams, protoPoolReservesAddresses, - addressesProvider, - lendingPoolProxy, testHelpers, - lendingPoolConfiguratorProxy, - AavePools.proto, - ZERO_ADDRESS, - verify + admin, + ZERO_ADDRESS ); await enableReservesToBorrow( reservesParams, diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 6423b09d..d7a171e5 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -11,7 +11,7 @@ import {waitForTx} from '../../helpers/misc-utils'; import { enableReservesToBorrow, enableReservesAsCollateral, - initReserves, + initReservesByHelper, } from '../../helpers/init-helpers'; import {ZERO_ADDRESS} from '../../helpers/constants'; import {exit} from 'process'; @@ -27,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 = localBRE.network.name; const poolConfig = loadPoolConfig(pool); const {ReserveAssets, ReservesConfig} = poolConfig as ICommonConfiguration; @@ -40,16 +39,20 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') const testHelpers = await deployAaveProtocolTestHelpers(addressesProvider.address, verify); - await initReserves( + const admin = await addressesProvider.getAaveAdmin(); + if (!reserveAssets) { + throw 'Reserve assets is undefined. Check ReserveAssets configuration at config directory'; + } + + await initReservesByHelper( + lendingPoolProxy.address, + addressesProvider.address, + lendingPoolConfiguratorProxy.address, ReservesConfig, reserveAssets, - addressesProvider, - lendingPoolProxy, testHelpers, - lendingPoolConfiguratorProxy, - AavePools.proto, - ZERO_ADDRESS, - verify + admin, + ZERO_ADDRESS ); await enableReservesToBorrow( ReservesConfig, diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index 3b84cb94..b69326dc 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -35,6 +35,7 @@ import { enableReservesToBorrow, enableReservesAsCollateral, initReserves, + initReservesByHelper, } from '../helpers/init-helpers'; import {AaveConfig} from '../config/aave'; import {ZERO_ADDRESS} from '../helpers/constants'; @@ -206,16 +207,15 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { await insertContractAddressInDb(eContractid.AaveProtocolTestHelpers, testHelpers.address); console.log('Initialize configuration'); - await initReserves( + await initReservesByHelper( + lendingPoolProxy.address, + addressesProvider.address, + lendingPoolConfiguratorProxy.address, reservesParams, protoPoolReservesAddresses, - addressesProvider, - lendingPoolProxy, testHelpers, - lendingPoolConfiguratorProxy, - AavePools.proto, - ZERO_ADDRESS, - false + await deployer.getAddress(), + ZERO_ADDRESS ); await enableReservesToBorrow( reservesParams, diff --git a/test/helpers/make-suite.ts b/test/helpers/make-suite.ts index 11e8c9f8..198ffa5f 100644 --- a/test/helpers/make-suite.ts +++ b/test/helpers/make-suite.ts @@ -97,13 +97,10 @@ 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 aDaiAddress = allTokens.find((aToken) => aToken.symbol === 'aDAI')?.tokenAddress; - const aEthAddress = (await testEnv.helpersContract.getAllATokens()).find( - (aToken) => aToken.symbol === 'aETH' - )?.tokenAddress; + const aEthAddress = allTokens.find((aToken) => aToken.symbol === 'aETH')?.tokenAddress; const reservesTokens = await testEnv.helpersContract.getAllReservesTokens(); diff --git a/test/test-init.spec.ts b/test/test-init.ts similarity index 98% rename from test/test-init.spec.ts rename to test/test-init.ts index 290f7018..982b8796 100644 --- a/test/test-init.spec.ts +++ b/test/test-init.ts @@ -35,6 +35,7 @@ import { import AaveConfig from '../config/aave'; import {DeployTokensFactory} from '../types'; 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; @@ -181,7 +182,9 @@ makeSuite('Init helper test', (testEnv: TestEnv) => { lendingPoolConfiguratorProxy.address, reservesParams, protoPoolReservesAddresses, - testHelpers + testHelpers, + await deployer.getAddress(), + ZERO_ADDRESS ); }); }); From e6be323e511b820c52361660bd5689cf4733cd92 Mon Sep 17 00:00:00 2001 From: David Racero Date: Fri, 23 Oct 2020 18:41:52 +0200 Subject: [PATCH 09/33] Remove unneeded factory --- helpers/init-helpers.ts | 3 --- test/test-init.ts | 1 - 2 files changed, 4 deletions(-) diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index f88c2620..2babe23c 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -10,12 +10,9 @@ import { deployGenericAToken, } from './contracts-deployments'; import {chunk, waitForTx} from './misc-utils'; -import {DeployTokens} from '../types/DeployTokens'; -import {ZERO_ADDRESS} from './constants'; import {getFirstSigner, getLendingPoolAddressesProvider} from './contracts-getters'; import {DeployATokensAndRatesFactory} from '../types/DeployATokensAndRatesFactory'; import {DeployStableAndVariableTokensFactory} from '../types/DeployStableAndVariableTokensFactory'; -import {getDefaultSettings} from 'http2'; export const enableReservesToBorrow = async ( reservesParams: iMultiPoolsAssets, diff --git a/test/test-init.ts b/test/test-init.ts index 982b8796..2dcacdf8 100644 --- a/test/test-init.ts +++ b/test/test-init.ts @@ -33,7 +33,6 @@ import { setInitialMarketRatesInRatesOracle, } from '../helpers/oracles-helpers'; import AaveConfig from '../config/aave'; -import {DeployTokensFactory} from '../types'; import {initReservesByHelper} from '../helpers/init-helpers'; import {ZERO_ADDRESS} from '../helpers/constants'; From 41592c4b48eb0366bb309ffc783a6b6c0ae5de71 Mon Sep 17 00:00:00 2001 From: David Racero Date: Mon, 26 Oct 2020 11:53:00 +0100 Subject: [PATCH 10/33] Fix package lock CI --- package-lock.json | 104 ++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 46 deletions(-) diff --git a/package-lock.json b/package-lock.json index 51b67993..8cd9d2e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2094,9 +2094,9 @@ "dev": true }, "@types/qs": { - "version": "6.9.3", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz", - "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==", + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", + "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==", "dev": true }, "@types/resolve": { @@ -2889,12 +2889,12 @@ "dev": true }, "buidler-gas-reporter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/buidler-gas-reporter/-/buidler-gas-reporter-0.1.3.tgz", - "integrity": "sha512-3Q27K52iGEghJ4icDdkV/67iJiRCaiZ39E2LLCBNZgx5NvltI5Q7oR3RVyCGO/m3SZBcj418zC8p7yeyj/jFdw==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/buidler-gas-reporter/-/buidler-gas-reporter-0.1.4.tgz", + "integrity": "sha512-objSu/tGggxKDmlpZViM9uEKRSo7vXxBsPv+vXegre1AWapJXQNfJPtBmrNvnT5Ixl8pecWSRXsfO95nJAn4yw==", "dev": true, "requires": { - "eth-gas-reporter": "^0.2.13" + "eth-gas-reporter": "^0.2.18" } }, "buidler-typechain": { @@ -4108,13 +4108,13 @@ } }, "eth-gas-reporter": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.17.tgz", - "integrity": "sha512-MsrUqeXTAFU9QEdAIdaVu+QeU1XwFsKvPDEC68iheppVR5xUP11h4SyPhSRZiGfOzXr1CfTtPM/B6wPGtt7/LA==", + "version": "0.2.18", + "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.18.tgz", + "integrity": "sha512-P6LQ1QmU9bqU4zmd01Ws/b2EWAD5rT771U0wyJ/c+fKE6RdE9ks8KzjdR1zjosV2uilMfqVTtrBrXveCOnaTyQ==", "dev": true, "requires": { "@ethersproject/abi": "^5.0.0-beta.146", - "@solidity-parser/parser": "^0.5.2", + "@solidity-parser/parser": "^0.8.0", "cli-table3": "^0.5.0", "colors": "^1.1.2", "ethereumjs-util": "6.2.0", @@ -4130,6 +4130,27 @@ "sync-request": "^6.0.0" }, "dependencies": { + "@solidity-parser/parser": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.8.1.tgz", + "integrity": "sha512-DF7H6T8I4lo2IZOE2NZwt3631T8j1gjpQLjmvY2xBNK50c4ltslR4XPKwT6RkeSd4+xCAK0GHC/k7sbRDBE4Yw==", + "dev": true + }, + "elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, "ethereumjs-util": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz", @@ -4146,37 +4167,20 @@ } }, "ethers": { - "version": "4.0.47", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.47.tgz", - "integrity": "sha512-hssRYhngV4hiDNeZmVU/k5/E8xmLG8UpcNUzg6mb7lqhgpFPH/t7nuv20RjRrEf0gblzvi2XwR5Te+V3ZFc9pQ==", + "version": "4.0.48", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.48.tgz", + "integrity": "sha512-sZD5K8H28dOrcidzx9f8KYh8083n5BexIO3+SbE4jK83L85FxtpXZBCQdXb8gkg+7sBqomcLhhkU7UHL+F7I2g==", "dev": true, "requires": { "aes-js": "3.0.0", "bn.js": "^4.4.0", - "elliptic": "6.5.2", + "elliptic": "6.5.3", "hash.js": "1.1.3", "js-sha3": "0.5.7", "scrypt-js": "2.0.4", "setimmediate": "1.0.4", "uuid": "2.0.1", "xmlhttprequest": "1.8.0" - }, - "dependencies": { - "elliptic": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", - "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - } } }, "hash.js": { @@ -21252,9 +21256,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.26", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.26.tgz", - "integrity": "sha512-myMwkO2Cr82kirHY8uknNRHEVtn0wV3DTQfkrjx17jmkstDRZ24gNUdl8AHXVyVclTYI/bNjgTPTAWvWLqXqkw==", + "version": "10.17.42", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.42.tgz", + "integrity": "sha512-HElxYF7C/MSkuvlaHB2c+82zhXiuO49Cq056Dol8AQuTph7oJtduo2n6J8rFa+YhJyNgQ/Lm20ZaxqD0vxU0+Q==", "dev": true } } @@ -23736,21 +23740,29 @@ } }, "request-promise-core": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", - "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", "dev": true, "requires": { - "lodash": "^4.17.15" + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "request-promise-native": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", - "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", "dev": true, "requires": { - "request-promise-core": "1.1.3", + "request-promise-core": "1.1.4", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" } @@ -24746,9 +24758,9 @@ }, "dependencies": { "@types/node": { - "version": "8.10.61", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.61.tgz", - "integrity": "sha512-l+zSbvT8TPRaCxL1l9cwHCb0tSqGAGcjPJFItGGYat5oCTiq1uQQKYg5m7AF1mgnEBzFXGLJ2LRmNjtreRX76Q==", + "version": "8.10.65", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.65.tgz", + "integrity": "sha512-xdcqtQl1g3p/49kmcj7ZixPWOcNHA1tYNz+uN0PJEcgtN6zywK74aacTnd3eFGPuBpD7kK8vowmMRkUt6jHU/Q==", "dev": true } } From 24d5c4766f9ad5002a49f5381c6ca274371d0424 Mon Sep 17 00:00:00 2001 From: David Truong Date: Mon, 26 Oct 2020 13:27:31 +0100 Subject: [PATCH 11/33] [WIP] Adding onBehalfOf to flashloan --- contracts/interfaces/ILendingPool.sol | 1 + contracts/lendingpool/LendingPool.sol | 4 +- test/flashloan.spec.ts | 74 +++++++++++++++++++++++---- 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/contracts/interfaces/ILendingPool.sol b/contracts/interfaces/ILendingPool.sol index 2b4ead37..813c6304 100644 --- a/contracts/interfaces/ILendingPool.sol +++ b/contracts/interfaces/ILendingPool.sol @@ -274,6 +274,7 @@ interface ILendingPool { address reserve, uint256 amount, uint256 debtType, + address onBehalfOf, bytes calldata params, uint16 referralCode ) external; diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index c1ff20bb..ff593199 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -498,6 +498,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage * @param asset The address of the principal reserve * @param amount The amount requested for this flashloan * @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 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 **/ @@ -506,6 +507,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage address asset, uint256 amount, uint256 mode, + address onBehalfOf, bytes calldata params, uint16 referralCode ) external override { @@ -549,7 +551,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage ExecuteBorrowParams( asset, msg.sender, - msg.sender, + onBehalfOf, vars.amountPlusPremium, mode, vars.aTokenAddress, diff --git a/test/flashloan.spec.ts b/test/flashloan.spec.ts index 1ca080f9..a8f2991c 100644 --- a/test/flashloan.spec.ts +++ b/test/flashloan.spec.ts @@ -51,6 +51,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { weth.address, ethers.utils.parseEther('0.8'), 0, + _mockFlashLoanReceiver.address, '0x10', '0' ); @@ -80,6 +81,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { weth.address, '1000720000000000000', 0, + _mockFlashLoanReceiver.address, '0x10', '0' ); @@ -111,6 +113,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { weth.address, ethers.utils.parseEther('0.8'), 0, + _mockFlashLoanReceiver.address, '0x10', '0' ) @@ -131,6 +134,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { weth.address, ethers.utils.parseEther('0.8'), 0, + _mockFlashLoanReceiver.address, '0x10', '0' ) @@ -151,6 +155,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { weth.address, ethers.utils.parseEther('0.8'), 4, + _mockFlashLoanReceiver.address, '0x10', '0' ) @@ -179,6 +184,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { weth.address, ethers.utils.parseEther('0.8'), 2, + caller.address, '0x10', '0' ); @@ -197,14 +203,16 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { }); it('tries to take a very small flashloan, which would result in 0 fees (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, '1', //1 wei loan 2, + caller.address, '0x10', '0' ) @@ -212,14 +220,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' ), @@ -228,10 +238,21 @@ 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 + .connect(caller.signer) + .flashLoan( + deployer.address, + weth.address, + '1000000000000000000', + 2, + caller.address, + '0x10', + '0' + ) ).to.be.reverted; }); @@ -260,6 +281,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { usdc.address, flashloanAmount, 0, + _mockFlashLoanReceiver.address, '0x10', '0' ); @@ -297,7 +319,15 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { await expect( pool .connect(caller.signer) - .flashLoan(_mockFlashLoanReceiver.address, usdc.address, flashloanAmount, 2, '0x10', '0') + .flashLoan( + _mockFlashLoanReceiver.address, + usdc.address, + flashloanAmount, + 0, + _mockFlashLoanReceiver.address, + '0x10', + '0' + ) ).to.be.revertedWith(COLLATERAL_BALANCE_IS_0); }); @@ -320,7 +350,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.signer, + '0x10', + '0' + ); const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses( usdc.address ); @@ -355,7 +393,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, + _mockFlashLoanReceiver.address, + '0x10', + '0' + ) ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); }); @@ -370,7 +416,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.signer, + '0x10', + '0' + ); const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address); From e17f2ec814054a2094b665419207185e5aeac26c Mon Sep 17 00:00:00 2001 From: David Racero Date: Mon, 26 Oct 2020 17:43:10 +0100 Subject: [PATCH 12/33] Added collateral enable and stable migration optimization. --- ...AndRates.sol => ATokensAndRatesHelper.sol} | 35 +- ....sol => StableAndVariableTokensHelper.sol} | 3 +- deployed-contracts.json | 62 +++- helpers/contracts-deployments.ts | 24 ++ helpers/contracts-getters.ts | 23 +- helpers/init-helpers.ts | 335 +++++++----------- helpers/oracles-helpers.ts | 1 - helpers/types.ts | 2 + tasks/dev/5_initialize.ts | 16 +- tasks/full/5_initialize.ts | 25 +- test/__setup.spec.ts | 17 +- 11 files changed, 289 insertions(+), 254 deletions(-) rename contracts/deployments/{DeployATokensAndRates.sol => ATokensAndRatesHelper.sol} (72%) rename contracts/deployments/{DeployStableAndVariableTokens.sol => StableAndVariableTokensHelper.sol} (94%) diff --git a/contracts/deployments/DeployATokensAndRates.sol b/contracts/deployments/ATokensAndRatesHelper.sol similarity index 72% rename from contracts/deployments/DeployATokensAndRates.sol rename to contracts/deployments/ATokensAndRatesHelper.sol index 7aac70b3..a51de6a5 100644 --- a/contracts/deployments/DeployATokensAndRates.sol +++ b/contracts/deployments/ATokensAndRatesHelper.sol @@ -10,7 +10,7 @@ import { DefaultReserveInterestRateStrategy } from '../lendingpool/DefaultReserveInterestRateStrategy.sol'; -contract DeployATokensAndRates { +contract ATokensAndRatesHelper { address payable private pool; address private addressesProvider; address private poolConfigurator; @@ -87,4 +87,37 @@ contract DeployATokensAndRates { ); } } + + function enableReservesAsCollateral( + address[] calldata tokens, + uint256[] calldata baseLTVs, + uint256[] calldata liquidationThresholds, + uint256[] calldata liquidationBonuses + ) external { + 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 + { + require(stableBorrows.length == tokens.length); + + for (uint256 i = 0; i < tokens.length; i++) { + LendingPoolConfigurator(poolConfigurator).enableBorrowingOnReserve( + tokens[i], + stableBorrows[i] + ); + } + } } diff --git a/contracts/deployments/DeployStableAndVariableTokens.sol b/contracts/deployments/StableAndVariableTokensHelper.sol similarity index 94% rename from contracts/deployments/DeployStableAndVariableTokens.sol rename to contracts/deployments/StableAndVariableTokensHelper.sol index 2a5fe075..a688084a 100644 --- a/contracts/deployments/DeployStableAndVariableTokens.sol +++ b/contracts/deployments/StableAndVariableTokensHelper.sol @@ -4,9 +4,8 @@ pragma experimental ABIEncoderV2; import {StableDebtToken} from '../tokenization/StableDebtToken.sol'; import {VariableDebtToken} from '../tokenization/VariableDebtToken.sol'; -import '@nomiclabs/buidler/console.sol'; -contract DeployStableAndVariableTokens { +contract StableAndVariableTokensHelper { address payable private pool; address private addressesProvider; event deployedContracts(address stableToken, address variableToken); diff --git a/deployed-contracts.json b/deployed-contracts.json index 9891a3ca..9d9ddc8a 100644 --- a/deployed-contracts.json +++ b/deployed-contracts.json @@ -27,7 +27,7 @@ "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "kovan": { - "address": "0xF9a2E6D57c691f3aa5269858178a13Ef06378579", + "address": "0x4Fa53B048dbf5F87324C81639984619aB1D98ff7", "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } }, @@ -45,7 +45,7 @@ "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "kovan": { - "address": "0xf3266d89e6742fAE2C35D05eD549cd4e117300a7", + "address": "0x87223624f91EaA7B0627Bf81F541D4F6A1083072", "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } }, @@ -76,7 +76,7 @@ "address": "0x9Ec55627757348b322c8dD0865D704649bFa0c7b" }, "kovan": { - "address": "0x1aae278bCcdb95817c7A546d752fC662F09b6DBa" + "address": "0x633CD212D4f7aa6d221353Fb9c6edB746498cC8C" } }, "LendingPoolDataProvider": { @@ -92,7 +92,7 @@ "address": "0x3EE716e38f21e5FC16BFDB773db24D63C637A5d8" }, "kovan": { - "address": "0x8E05A3054cb736258FaF4638D07058cE6e294d2C" + "address": "0xAD7abA67B6A32de493f684f3c418E324312da0f7" } }, "PriceOracle": { @@ -224,7 +224,7 @@ }, "MockFlashLoanReceiver": { "buidlerevm": { - "address": "0xB8054085AF605D93c32E6B829d3d7eA2A8C84F9A" + "address": "0x2530ce07D254eA185E8e0bCC37a39e2FbA3bE548" }, "localhost": { "address": "0x9c91aEaD98b1354C7B0EAfb8ff539d0796c79894" @@ -235,7 +235,7 @@ }, "WalletBalanceProvider": { "buidlerevm": { - "address": "0xA3Ab089388B0C1BA83B3496696242FcA3F8eb9D5", + "address": "0x0Cf45557d25a4e4c0F1aC65EF6c48ae67c61a0E6", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -245,6 +245,10 @@ "coverage": { "address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + }, + "kovan": { + "address": "0x067400A1e5DfaD5B7537acfd1c981F62c22Ea53E", + "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } }, "DAI": { @@ -580,7 +584,7 @@ "address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4" }, "kovan": { - "address": "0xfF28b837352d9531bAb6dFF3650D7831192117F7", + "address": "0x9A82710F3fFEF29e5940F3D5f15E8d8d9CaF8C44", "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } }, @@ -640,7 +644,7 @@ }, "MockAToken": { "buidlerevm": { - "address": "0x2dC17ABe95C889aA4c9474eD45Dd454Ed1Ec1ec1", + "address": "0x7fAeC7791277Ff512c41CA903c177B2Ed952dDAc", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -668,7 +672,7 @@ }, "MockStableDebtToken": { "buidlerevm": { - "address": "0x8b949D7E587518A6ad727ef30C5815De4a16A0D7", + "address": "0x33958cC3535Fc328369EAC2B2Bebd120D67C7fa1", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -682,7 +686,7 @@ }, "MockVariableDebtToken": { "buidlerevm": { - "address": "0xCC5F3Be6e695bD0239dFd0efC8E9FFC6E969D29e", + "address": "0x2cBbbBE1B75Ad7848F0844215816F551f429c64f", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -708,24 +712,60 @@ "buidlerevm": { "address": "0xFAe0fd738dAbc8a0426F47437322b6d026A9FD95", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + }, + "kovan": { + "address": "0xd9A66F000e278710a44525AC43EAE38c63984a23", + "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } }, "GenericLogic": { "buidlerevm": { "address": "0x6082731fdAba4761277Fb31299ebC782AD3bCf24", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + }, + "kovan": { + "address": "0xF412a3A5Ae0CBDc0809d27DE317F531e7477C03f", + "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } }, "ValidationLogic": { "buidlerevm": { "address": "0x8456161947DFc1fC159A0B26c025cD2b4bba0c3e", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + }, + "kovan": { + "address": "0x3F6d595c3b83E4F35601B51B05B7862381d459f6", + "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } }, "LendingPoolCollateralManager": { "buidlerevm": { - "address": "0xeB80313502EA077FA9B8E89b45e4a1B236cA17Ea", + "address": "0x8BFFF31B1757da579Bb5B118489568526F7fb6D4", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + }, + "kovan": { + "address": "0x1A9333aA3e524463680FAcE1F734c47D681b32ed", + "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" + } + }, + "StableAndVariableTokensHelper": { + "buidlerevm": { + "address": "0x3392c115Ff2CE1A782B4a965fF770da61e69228E", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + }, + "kovan": { + "address": "0x1d8496a2C0e78008dDDF56c84b1d0f14707D3323", + "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" + } + }, + "ATokensAndRatesHelper": { + "buidlerevm": { + "address": "0x72358bcB1b8B60Ca2f30244e50Be20C3ecaC74B2", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + }, + "kovan": { + "address": "0xbaAa0c348ed045eF7c57136578339b20d6c375AE", + "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } } } diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index dc10288d..82ac2d97 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -20,6 +20,7 @@ import {ZERO_ADDRESS} from './constants'; import { AaveProtocolTestHelpersFactory, ATokenFactory, + ATokensAndRatesHelperFactory, ChainlinkProxyPriceProviderFactory, DefaultReserveInterestRateStrategyFactory, InitializableAdminUpgradeabilityProxyFactory, @@ -40,6 +41,7 @@ import { WalletBalanceProviderFactory, } from '../types'; import {withSaveAndVerify, registerContractInJsonDb, linkBytecode} from './contracts-helpers'; +import {StableAndVariableTokensHelperFactory} from '../types/StableAndVariableTokensHelperFactory'; export const deployLendingPoolAddressesProvider = async (verify?: boolean) => withSaveAndVerify( @@ -350,3 +352,25 @@ export const deployMockTokens = async (config: PoolConfiguration, verify?: boole } 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 + ); diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index 231b87e0..21b5e5b7 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -2,6 +2,8 @@ import { AaveProtocolTestHelpersFactory, ATokenFactory, DefaultReserveInterestRateStrategyFactory, + DeployATokensAndRatesFactory, + DeployStableAndVariableTokensFactory, GenericLogicFactory, LendingPoolAddressesProviderFactory, LendingPoolAddressesProviderRegistryFactory, @@ -16,7 +18,7 @@ import { VariableDebtTokenFactory, } from '../types'; import {Ierc20DetailedFactory} from '../types/Ierc20DetailedFactory'; -import {getContract, MockTokenMap} from './contracts-helpers'; +import {MockTokenMap} from './contracts-helpers'; import {BRE, getDb} from './misc-utils'; import {eContractid, PoolConfiguration, tEthereumAddress, TokenContractId} from './types'; @@ -201,3 +203,22 @@ export const getGenericLogic = async (address?: tEthereumAddress) => (await getDb().get(`${eContractid.GenericLogic}.${BRE.network.name}`).value()).address, await getFirstSigner() ); + +export const getStableAndVariableTokensHelper = async (address?: tEthereumAddress) => + await DeployStableAndVariableTokensFactory.connect( + address || + ( + await getDb() + .get(`${eContractid.StableAndVariableTokensHelper}.${BRE.network.name}`) + .value() + ).address, + await getFirstSigner() + ); + +export const getATokensAndRatesHelper = async (address?: tEthereumAddress) => + await DeployATokensAndRatesFactory.connect( + address || + (await getDb().get(`${eContractid.ATokensAndRatesHelper}.${BRE.network.name}`).value()) + .address, + await getFirstSigner() + ); diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index a701a350..643fb08c 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -1,106 +1,12 @@ -import {AavePools, iMultiPoolsAssets, IReserveParams, tEthereumAddress} from './types'; -import {LendingPool} from '../types/LendingPool'; +import {iMultiPoolsAssets, IReserveParams, tEthereumAddress} from './types'; import {LendingPoolConfigurator} from '../types/LendingPoolConfigurator'; import {AaveProtocolTestHelpers} from '../types/AaveProtocolTestHelpers'; -import {LendingPoolAddressesProvider} from '../types/LendingPoolAddressesProvider'; import { - deployDefaultReserveInterestRateStrategy, - deployStableDebtToken, - deployVariableDebtToken, - deployGenericAToken, + deployATokensAndRatesHelper, + deployStableAndVariableTokensHelper, } from './contracts-deployments'; import {chunk, waitForTx} from './misc-utils'; -import {getFirstSigner, getLendingPoolAddressesProvider} from './contracts-getters'; -import {DeployATokensAndRatesFactory} from '../types/DeployATokensAndRatesFactory'; -import {DeployStableAndVariableTokensFactory} from '../types/DeployStableAndVariableTokensFactory'; - -export const enableReservesToBorrow = async ( - reservesParams: iMultiPoolsAssets, - tokenAddresses: {[symbol: string]: tEthereumAddress}, - helpers: AaveProtocolTestHelpers, - lendingPoolConfigurator: LendingPoolConfigurator -) => { - for (const [assetSymbol, {borrowingEnabled, stableBorrowRateEnabled}] of Object.entries( - reservesParams - ) as [string, IReserveParams][]) { - if (!borrowingEnabled) continue; - try { - 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.` - ); - } - } -}; - -export const enableReservesAsCollateral = async ( - reservesParams: iMultiPoolsAssets, - tokenAddresses: {[symbol: string]: tEthereumAddress}, - helpers: AaveProtocolTestHelpers, - lendingPoolConfigurator: LendingPoolConfigurator -) => { - for (const [ - assetSymbol, - {baseLTVAsCollateral, liquidationBonus, liquidationThreshold}, - ] of Object.entries(reservesParams) as [string, IReserveParams][]) { - if (baseLTVAsCollateral === '-1') continue; - - const assetAddressIndex = Object.keys(tokenAddresses).findIndex( - (value) => value === assetSymbol - ); - const [, tokenAddress] = (Object.entries(tokenAddresses) as [string, string][])[ - assetAddressIndex - ]; - const {usageAsCollateralEnabled: alreadyEnabled} = await helpers.getReserveConfigurationData( - tokenAddress - ); - - if (alreadyEnabled) { - console.log(`Reserve ${assetSymbol} is already enabled as collateral, skipping`); - continue; - } - - try { - console.log(`Enabling reserve ${assetSymbol} as collateral`); - - await waitForTx( - await lendingPoolConfigurator.enableReserveAsCollateral( - tokenAddress, - baseLTVAsCollateral, - liquidationThreshold, - liquidationBonus - ) - ); - } catch (e) { - console.log( - `Enabling reserve as collateral for ${assetSymbol} failed with error ${e}. Skipped.` - ); - } - } -}; +import {getATokensAndRatesHelper, getLendingPoolAddressesProvider} from './contracts-getters'; export const initReservesByHelper = async ( lendingPoolProxy: tEthereumAddress, @@ -110,16 +16,18 @@ export const initReservesByHelper = async ( tokenAddresses: {[symbol: string]: tEthereumAddress}, helpers: AaveProtocolTestHelpers, admin: tEthereumAddress, - incentivesController: tEthereumAddress + incentivesController: tEthereumAddress, + verify?: boolean ) => { - const stableAndVariableDeployer = await new DeployStableAndVariableTokensFactory( - await getFirstSigner() - ).deploy(lendingPoolProxy, addressesProvider); - await waitForTx(stableAndVariableDeployer.deployTransaction); - const atokenAndRatesDeployer = await new DeployATokensAndRatesFactory( - await getFirstSigner() - ).deploy(lendingPoolProxy, addressesProvider, lendingPoolConfigurator); - await waitForTx(atokenAndRatesDeployer.deployTransaction); + const stableAndVariableDeployer = await deployStableAndVariableTokensHelper( + [lendingPoolProxy, addressesProvider], + verify + ); + const atokenAndRatesDeployer = await deployATokensAndRatesHelper([ + lendingPoolProxy, + addressesProvider, + lendingPoolConfigurator, + ]); const addressProvider = await getLendingPoolAddressesProvider(addressesProvider); // Set aTokenAndRatesDeployer as temporal admin @@ -269,121 +177,140 @@ export const getPairsTokenAggregator = ( return [mappedPairs, mappedAggregators]; }; -export const initReserves = async ( +export const enableReservesToBorrowByHelper = async ( reservesParams: iMultiPoolsAssets, tokenAddresses: {[symbol: string]: tEthereumAddress}, - lendingPoolAddressesProvider: LendingPoolAddressesProvider, - lendingPool: LendingPool, helpers: AaveProtocolTestHelpers, - lendingPoolConfigurator: LendingPoolConfigurator, - aavePool: AavePools, - incentivesController: tEthereumAddress, - verify: boolean + admin: tEthereumAddress ) => { - if (aavePool !== AavePools.proto && aavePool !== AavePools.secondary) { - console.log(`Invalid Aave pool ${aavePool}`); - process.exit(1); - } + const addressProvider = await getLendingPoolAddressesProvider(); + const atokenAndRatesDeployer = await getATokensAndRatesHelper(); + const tokens: string[] = []; + const symbols: string[] = []; + const stableEnabled: boolean[] = []; - for (let [assetSymbol, {reserveDecimals}] of Object.entries(reservesParams) as [ - string, - IReserveParams - ][]) { + // 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 + ); - const {isActive: reserveInitialized} = await helpers.getReserveConfigurationData(tokenAddress); - - if (reserveInitialized) { - console.log(`Reserve ${assetSymbol} is already active, skipping configuration`); + 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)); - 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 - ); + // Deploy init per chunks + const stableChunks = 20; + const chunkedTokens = chunk(tokens, stableChunks); + const chunkedSymbols = chunk(symbols, stableChunks); + const chunkedStableEnabled = chunk(stableEnabled, stableChunks); - 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(`- 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('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.`); + console.log(` - Init for: ${chunkedSymbols[chunkIndex].join(', ')}`); } + // Set deployer back as admin + await waitForTx(await addressProvider.setAaveAdmin(admin)); + } +}; + +export const enableReservesAsCollateralByHelper = async ( + reservesParams: iMultiPoolsAssets, + 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}, + ] of Object.entries(reservesParams) as [string, IReserveParams][]) { + if (baseLTVAsCollateral === '-1') continue; + + const assetAddressIndex = Object.keys(tokenAddresses).findIndex( + (value) => value === assetSymbol + ); + const [, tokenAddress] = (Object.entries(tokenAddresses) as [string, string][])[ + assetAddressIndex + ]; + const {usageAsCollateralEnabled: alreadyEnabled} = await helpers.getReserveConfigurationData( + tokenAddress + ); + + if (alreadyEnabled) { + 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)); + + // 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 atokenAndRatesDeployer.enableReservesAsCollateral( + chunkedTokens[chunkIndex], + chunkedBase[chunkIndex], + chunkedliquidationThresholds[chunkIndex], + chunkedliquidationBonuses[chunkIndex], + {gasLimit: 12000000} + ) + ); + console.log(` - Init for: ${chunkedSymbols[chunkIndex].join(', ')}`); + } + // Set deployer back as admin + await waitForTx(await addressProvider.setAaveAdmin(admin)); } }; diff --git a/helpers/oracles-helpers.ts b/helpers/oracles-helpers.ts index b4473be2..2837a265 100644 --- a/helpers/oracles-helpers.ts +++ b/helpers/oracles-helpers.ts @@ -13,7 +13,6 @@ import {PriceOracle} from '../types/PriceOracle'; import {MockAggregator} from '../types/MockAggregator'; import {deployMockAggregator} from './contracts-deployments'; import {waitForTx} from './misc-utils'; -import {verifyContract} from './etherscan-verification'; export const setInitialMarketRatesInRatesOracle = async ( marketRates: iMultiPoolsAssets, diff --git a/helpers/types.ts b/helpers/types.ts index 305ec335..44a2452a 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -55,6 +55,8 @@ export enum eContractid { VariableDebtToken = 'VariableDebtToken', FeeProvider = 'FeeProvider', TokenDistributor = 'TokenDistributor', + StableAndVariableTokensHelper = 'StableAndVariableTokensHelper', + ATokensAndRatesHelper = 'ATokensAndRatesHelper', } export enum ProtocolErrors { diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index 213ed6cd..25fdb88d 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -10,9 +10,8 @@ import {getReservesConfigByPool} from '../../helpers/configuration'; import {tEthereumAddress, AavePools, eContractid} from '../../helpers/types'; import {waitForTx, filterMapBy} from '../../helpers/misc-utils'; import { - enableReservesToBorrow, - enableReservesAsCollateral, - initReserves, + enableReservesToBorrowByHelper, + enableReservesAsCollateralByHelper, initReservesByHelper, } from '../../helpers/init-helpers'; import {getAllTokenAddresses} from '../../helpers/mock-helpers'; @@ -55,19 +54,20 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') protoPoolReservesAddresses, testHelpers, admin, - ZERO_ADDRESS + ZERO_ADDRESS, + verify ); - await enableReservesToBorrow( + await enableReservesToBorrowByHelper( reservesParams, protoPoolReservesAddresses, testHelpers, - lendingPoolConfiguratorProxy + admin ); - await enableReservesAsCollateral( + await enableReservesAsCollateralByHelper( reservesParams, protoPoolReservesAddresses, testHelpers, - lendingPoolConfiguratorProxy + admin ); const collateralManager = await deployLendingPoolCollateralManager(verify); diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index d7a171e5..3b296952 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -6,20 +6,20 @@ import { deployAaveProtocolTestHelpers, } from '../../helpers/contracts-deployments'; import {loadPoolConfig, ConfigNames} from '../../helpers/configuration'; -import {AavePools, eEthereumNetwork, ICommonConfiguration} from '../../helpers/types'; +import {eEthereumNetwork, ICommonConfiguration} from '../../helpers/types'; import {waitForTx} from '../../helpers/misc-utils'; import { - enableReservesToBorrow, - enableReservesAsCollateral, initReservesByHelper, + enableReservesToBorrowByHelper, + enableReservesAsCollateralByHelper, } from '../../helpers/init-helpers'; -import {ZERO_ADDRESS} from '../../helpers/constants'; import {exit} from 'process'; import { getLendingPool, getLendingPoolConfiguratorProxy, getLendingPoolAddressesProvider, } from '../../helpers/contracts-getters'; +import {ZERO_ADDRESS} from '../../helpers/constants'; task('full:initialize-lending-pool', 'Initialize lending pool configuration.') .addFlag('verify', 'Verify contracts at Etherscan') @@ -52,20 +52,11 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') reserveAssets, testHelpers, admin, - ZERO_ADDRESS - ); - await enableReservesToBorrow( - ReservesConfig, - reserveAssets, - testHelpers, - lendingPoolConfiguratorProxy - ); - await enableReservesAsCollateral( - ReservesConfig, - reserveAssets, - testHelpers, - lendingPoolConfiguratorProxy + ZERO_ADDRESS, + verify ); + await enableReservesToBorrowByHelper(ReservesConfig, reserveAssets, testHelpers, admin); + await enableReservesAsCollateralByHelper(ReservesConfig, reserveAssets, testHelpers, admin); const collateralManager = await deployLendingPoolCollateralManager(verify); await waitForTx( diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index 58b7ec4e..8f27d4d3 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -32,10 +32,9 @@ import { } from '../helpers/oracles-helpers'; import {waitForTx} from '../helpers/misc-utils'; import { - enableReservesToBorrow, - enableReservesAsCollateral, - initReserves, initReservesByHelper, + enableReservesToBorrowByHelper, + enableReservesAsCollateralByHelper, } from '../helpers/init-helpers'; import {AaveConfig} from '../config/aave'; import {ZERO_ADDRESS} from '../helpers/constants'; @@ -205,6 +204,7 @@ 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 initReservesByHelper( @@ -214,20 +214,20 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { reservesParams, protoPoolReservesAddresses, testHelpers, - await deployer.getAddress(), + admin, ZERO_ADDRESS ); - await enableReservesToBorrow( + await enableReservesToBorrowByHelper( reservesParams, protoPoolReservesAddresses, testHelpers, - lendingPoolConfiguratorProxy + admin ); - await enableReservesAsCollateral( + await enableReservesAsCollateralByHelper( reservesParams, protoPoolReservesAddresses, testHelpers, - lendingPoolConfiguratorProxy + admin ); const collateralManager = await deployLendingPoolCollateralManager(); @@ -245,7 +245,6 @@ 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...'); From 161fb63f1984ef9597f9881fd271a79d8fe90bdc Mon Sep 17 00:00:00 2001 From: David Racero Date: Tue, 27 Oct 2020 10:58:51 +0100 Subject: [PATCH 13/33] Added borrow rates deployment optimization and minor tweaks for deployment helpers --- .../deployments/ATokensAndRatesHelper.sol | 10 +++-- .../StableAndVariableTokensHelper.sol | 25 ++++++++++- deployed-contracts.json | 35 ++++++++------- helpers/contracts-getters.ts | 6 ++- helpers/init-helpers.ts | 29 +++++------- helpers/oracles-helpers.ts | 44 ++++++++++++++++--- tasks/dev/3_lending_pool.ts | 12 +++++ tasks/dev/4_oracles.ts | 8 ++-- tasks/dev/5_initialize.ts | 12 +---- tasks/full/2_lending_pool.ts | 11 +++++ tasks/full/3_oracles.ts | 9 ++-- tasks/full/5_initialize.ts | 12 +---- test/__setup.spec.ts | 29 ++++++------ 13 files changed, 150 insertions(+), 92 deletions(-) diff --git a/contracts/deployments/ATokensAndRatesHelper.sol b/contracts/deployments/ATokensAndRatesHelper.sol index a51de6a5..83146959 100644 --- a/contracts/deployments/ATokensAndRatesHelper.sol +++ b/contracts/deployments/ATokensAndRatesHelper.sol @@ -9,8 +9,9 @@ import {AToken} from '../tokenization/AToken.sol'; import { DefaultReserveInterestRateStrategy } from '../lendingpool/DefaultReserveInterestRateStrategy.sol'; +import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol'; -contract ATokensAndRatesHelper { +contract ATokensAndRatesHelper is Ownable { address payable private pool; address private addressesProvider; address private poolConfigurator; @@ -35,7 +36,7 @@ contract ATokensAndRatesHelper { string[] calldata symbols, uint256[5][] calldata rates, address incentivesController - ) external { + ) external onlyOwner { require(tokens.length == symbols.length, 't Arrays not same length'); require(rates.length == symbols.length, 'r Arrays not same length'); @@ -71,7 +72,7 @@ contract ATokensAndRatesHelper { address[] calldata aTokens, address[] calldata strategies, uint8[] calldata reserveDecimals - ) external { + ) external onlyOwner { require(variables.length == stables.length); require(aTokens.length == stables.length); require(strategies.length == stables.length); @@ -93,7 +94,7 @@ contract ATokensAndRatesHelper { uint256[] calldata baseLTVs, uint256[] calldata liquidationThresholds, uint256[] calldata liquidationBonuses - ) external { + ) external onlyOwner { require(baseLTVs.length == tokens.length); require(liquidationThresholds.length == tokens.length); require(liquidationBonuses.length == tokens.length); @@ -110,6 +111,7 @@ contract ATokensAndRatesHelper { function enableBorrowingOnReserves(address[] calldata tokens, bool[] calldata stableBorrows) external + onlyOwner { require(stableBorrows.length == tokens.length); diff --git a/contracts/deployments/StableAndVariableTokensHelper.sol b/contracts/deployments/StableAndVariableTokensHelper.sol index a688084a..c104758f 100644 --- a/contracts/deployments/StableAndVariableTokensHelper.sol +++ b/contracts/deployments/StableAndVariableTokensHelper.sol @@ -4,8 +4,10 @@ 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'; -contract StableAndVariableTokensHelper { +contract StableAndVariableTokensHelper is Ownable { address payable private pool; address private addressesProvider; event deployedContracts(address stableToken, address variableToken); @@ -23,7 +25,7 @@ contract StableAndVariableTokensHelper { address[] calldata tokens, string[] calldata symbols, address incentivesController - ) external { + ) 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++) { @@ -49,4 +51,23 @@ contract StableAndVariableTokensHelper { ); } } + + 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); + } } diff --git a/deployed-contracts.json b/deployed-contracts.json index 9d9ddc8a..3aa2b559 100644 --- a/deployed-contracts.json +++ b/deployed-contracts.json @@ -86,7 +86,8 @@ }, "LendingPool": { "buidlerevm": { - "address": "0xD9273d497eDBC967F39d419461CfcF382a0A822e" + "address": "0x35c1419Da7cf0Ff885B8Ef8EA9242FEF6800c99b", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { "address": "0x3EE716e38f21e5FC16BFDB773db24D63C637A5d8" @@ -97,7 +98,7 @@ }, "PriceOracle": { "buidlerevm": { - "address": "0x0C6c3C47A1f650809B0D1048FDf9603e09473D7E", + "address": "0xb682dEEf4f8e298d86bFc3e21f50c675151FB974", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -111,7 +112,7 @@ }, "MockAggregator": { "buidlerevm": { - "address": "0xc11f8E173ee67ffA7BBdD185D2399994AAd23Ec6", + "address": "0x3D8FFB457fedDFBc760F3F243283F52692b579B1", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -125,7 +126,7 @@ }, "ChainlinkProxyPriceProvider": { "buidlerevm": { - "address": "0xD662fb7FDC7526C79AA4417d2A4415416e057ec4", + "address": "0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -143,7 +144,7 @@ }, "LendingRateOracle": { "buidlerevm": { - "address": "0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89", + "address": "0xAF6BA11790D1942625C0c2dA07da19AB63845cfF", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -224,7 +225,7 @@ }, "MockFlashLoanReceiver": { "buidlerevm": { - "address": "0x2530ce07D254eA185E8e0bCC37a39e2FbA3bE548" + "address": "0xfC88832bac6AbdF216BC5A67be68E9DE94aD5ba2" }, "localhost": { "address": "0x9c91aEaD98b1354C7B0EAfb8ff539d0796c79894" @@ -235,7 +236,7 @@ }, "WalletBalanceProvider": { "buidlerevm": { - "address": "0x0Cf45557d25a4e4c0F1aC65EF6c48ae67c61a0E6", + "address": "0x1256eBA4d0a7A38D10BaF4F61775ba491Ce7EE25", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -575,7 +576,7 @@ }, "AaveProtocolTestHelpers": { "buidlerevm": { - "address": "0x93472C0e03215F9c33DA240Eb16703C8244eAa8c" + "address": "0xf4830d6b1D70C8595d3BD8A63f9ed9F636DB9ef2" }, "localhost": { "address": "0x987223924D2DD6c6efB601756850f3886ECbceF6" @@ -644,7 +645,7 @@ }, "MockAToken": { "buidlerevm": { - "address": "0x7fAeC7791277Ff512c41CA903c177B2Ed952dDAc", + "address": "0x77B0b5636fEA30eA79BB65AeCCdb599997A849A8", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -672,7 +673,7 @@ }, "MockStableDebtToken": { "buidlerevm": { - "address": "0x33958cC3535Fc328369EAC2B2Bebd120D67C7fa1", + "address": "0x78Ee8Fb9fE5abD5e347Fc94c2fb85596d1f60e3c", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -686,7 +687,7 @@ }, "MockVariableDebtToken": { "buidlerevm": { - "address": "0x2cBbbBE1B75Ad7848F0844215816F551f429c64f", + "address": "0x920d847fE49E54C19047ba8bc236C45A8068Bca7", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -710,7 +711,7 @@ }, "ReserveLogic": { "buidlerevm": { - "address": "0xFAe0fd738dAbc8a0426F47437322b6d026A9FD95", + "address": "0x78Ee8Fb9fE5abD5e347Fc94c2fb85596d1f60e3c", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "kovan": { @@ -720,7 +721,7 @@ }, "GenericLogic": { "buidlerevm": { - "address": "0x6082731fdAba4761277Fb31299ebC782AD3bCf24", + "address": "0x920d847fE49E54C19047ba8bc236C45A8068Bca7", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "kovan": { @@ -730,7 +731,7 @@ }, "ValidationLogic": { "buidlerevm": { - "address": "0x8456161947DFc1fC159A0B26c025cD2b4bba0c3e", + "address": "0xA4765Ff72A9F3CfE73089bb2c3a41B838DF71574", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "kovan": { @@ -740,7 +741,7 @@ }, "LendingPoolCollateralManager": { "buidlerevm": { - "address": "0x8BFFF31B1757da579Bb5B118489568526F7fb6D4", + "address": "0x8D0206fEBEB380486729b64bB4cfEDC5b354a6D6", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "kovan": { @@ -750,7 +751,7 @@ }, "StableAndVariableTokensHelper": { "buidlerevm": { - "address": "0x3392c115Ff2CE1A782B4a965fF770da61e69228E", + "address": "0x0C6c3C47A1f650809B0D1048FDf9603e09473D7E", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "kovan": { @@ -760,7 +761,7 @@ }, "ATokensAndRatesHelper": { "buidlerevm": { - "address": "0x72358bcB1b8B60Ca2f30244e50Be20C3ecaC74B2", + "address": "0x06bA8d8af0dF898D0712DffFb0f862cC51AF45c2", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "kovan": { diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index 21b5e5b7..3aefdab5 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -1,6 +1,7 @@ import { AaveProtocolTestHelpersFactory, ATokenFactory, + ATokensAndRatesHelperFactory, DefaultReserveInterestRateStrategyFactory, DeployATokensAndRatesFactory, DeployStableAndVariableTokensFactory, @@ -14,6 +15,7 @@ import { MockFlashLoanReceiverFactory, PriceOracleFactory, ReserveLogicFactory, + StableAndVariableTokensHelperFactory, StableDebtTokenFactory, VariableDebtTokenFactory, } from '../types'; @@ -205,7 +207,7 @@ export const getGenericLogic = async (address?: tEthereumAddress) => ); export const getStableAndVariableTokensHelper = async (address?: tEthereumAddress) => - await DeployStableAndVariableTokensFactory.connect( + await StableAndVariableTokensHelperFactory.connect( address || ( await getDb() @@ -216,7 +218,7 @@ export const getStableAndVariableTokensHelper = async (address?: tEthereumAddres ); export const getATokensAndRatesHelper = async (address?: tEthereumAddress) => - await DeployATokensAndRatesFactory.connect( + await ATokensAndRatesHelperFactory.connect( address || (await getDb().get(`${eContractid.ATokensAndRatesHelper}.${BRE.network.name}`).value()) .address, diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 643fb08c..61751052 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -6,35 +6,28 @@ import { deployStableAndVariableTokensHelper, } from './contracts-deployments'; import {chunk, waitForTx} from './misc-utils'; -import {getATokensAndRatesHelper, getLendingPoolAddressesProvider} from './contracts-getters'; +import { + getATokensAndRatesHelper, + getLendingPoolAddressesProvider, + getStableAndVariableTokensHelper, +} from './contracts-getters'; export const initReservesByHelper = async ( - lendingPoolProxy: tEthereumAddress, - addressesProvider: tEthereumAddress, - lendingPoolConfigurator: tEthereumAddress, reservesParams: iMultiPoolsAssets, tokenAddresses: {[symbol: string]: tEthereumAddress}, - helpers: AaveProtocolTestHelpers, admin: tEthereumAddress, - incentivesController: tEthereumAddress, - verify?: boolean + incentivesController: tEthereumAddress ) => { - const stableAndVariableDeployer = await deployStableAndVariableTokensHelper( - [lendingPoolProxy, addressesProvider], - verify - ); - const atokenAndRatesDeployer = await deployATokensAndRatesHelper([ - lendingPoolProxy, - addressesProvider, - lendingPoolConfigurator, - ]); - const addressProvider = await getLendingPoolAddressesProvider(addressesProvider); + 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 = 3; + const tokensChunks = 4; const initChunks = 6; // Deploy tokens and rates in chunks diff --git a/helpers/oracles-helpers.ts b/helpers/oracles-helpers.ts index 2837a265..45cec5e2 100644 --- a/helpers/oracles-helpers.ts +++ b/helpers/oracles-helpers.ts @@ -4,7 +4,6 @@ import { IMarketRates, iAssetBase, iAssetAggregatorBase, - eContractid, SymbolMap, } from './types'; @@ -12,13 +11,19 @@ import {LendingRateOracle} from '../types/LendingRateOracle'; import {PriceOracle} from '../types/PriceOracle'; import {MockAggregator} from '../types/MockAggregator'; import {deployMockAggregator} from './contracts-deployments'; -import {waitForTx} from './misc-utils'; +import {chunk, waitForTx} from './misc-utils'; +import {getStableAndVariableTokensHelper} from './contracts-getters'; -export const setInitialMarketRatesInRatesOracle = async ( +export const setInitialMarketRatesInRatesOracleByHelper = async ( marketRates: iMultiPoolsAssets, 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 @@ -29,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 ( diff --git a/tasks/dev/3_lending_pool.ts b/tasks/dev/3_lending_pool.ts index cc4bce81..866bd6b7 100644 --- a/tasks/dev/3_lending_pool.ts +++ b/tasks/dev/3_lending_pool.ts @@ -1,7 +1,9 @@ import {task} from '@nomiclabs/buidler/config'; import { + deployATokensAndRatesHelper, deployLendingPool, deployLendingPoolConfigurator, + deployStableAndVariableTokensHelper, } from '../../helpers/contracts-deployments'; import {eContractid} from '../../helpers/types'; import {waitForTx} from '../../helpers/misc-utils'; @@ -43,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 + ); }); diff --git a/tasks/dev/4_oracles.ts b/tasks/dev/4_oracles.ts index 415f6884..a20e2381 100644 --- a/tasks/dev/4_oracles.ts +++ b/tasks/dev/4_oracles.ts @@ -7,8 +7,8 @@ import { import { setInitialAssetPricesInOracle, - setInitialMarketRatesInRatesOracle, deployAllMockAggregators, + setInitialMarketRatesInRatesOracleByHelper, } from '../../helpers/oracles-helpers'; import {ICommonConfiguration, iAssetBase, TokenContractId} from '../../helpers/types'; import {waitForTx} from '../../helpers/misc-utils'; @@ -42,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)); @@ -67,9 +68,10 @@ task('dev:deploy-oracles', 'Deploy oracles for dev enviroment') const allReservesAddresses = { ...tokensAddressesWithoutUsd, }; - await setInitialMarketRatesInRatesOracle( + await setInitialMarketRatesInRatesOracleByHelper( LendingRateOracleRatesCommon, allReservesAddresses, - lendingRateOracle + lendingRateOracle, + admin ); }); diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index 25fdb88d..d4ce0c5d 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -46,17 +46,7 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') const admin = await addressesProvider.getAaveAdmin(); - await initReservesByHelper( - lendingPoolProxy.address, - addressesProvider.address, - lendingPoolConfiguratorProxy.address, - reservesParams, - protoPoolReservesAddresses, - testHelpers, - admin, - ZERO_ADDRESS, - verify - ); + await initReservesByHelper(reservesParams, protoPoolReservesAddresses, admin, ZERO_ADDRESS); await enableReservesToBorrowByHelper( reservesParams, protoPoolReservesAddresses, diff --git a/tasks/full/2_lending_pool.ts b/tasks/full/2_lending_pool.ts index cd498a0b..4a10b30c 100644 --- a/tasks/full/2_lending_pool.ts +++ b/tasks/full/2_lending_pool.ts @@ -1,8 +1,10 @@ import {task} from '@nomiclabs/buidler/config'; import {insertContractAddressInDb} from '../../helpers/contracts-helpers'; import { + deployATokensAndRatesHelper, deployLendingPool, deployLendingPoolConfigurator, + deployStableAndVariableTokensHelper, } from '../../helpers/contracts-deployments'; import {eContractid} from '../../helpers/types'; import {waitForTx} from '../../helpers/misc-utils'; @@ -46,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 + ); }); diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index 853330f2..a7a39a8c 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -4,7 +4,7 @@ import { deployChainlinkProxyPriceProvider, deployLendingRateOracle, } from '../../helpers/contracts-deployments'; -import {setInitialMarketRatesInRatesOracle} from '../../helpers/oracles-helpers'; +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'; @@ -30,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); @@ -58,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); diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 3b296952..ddc789d1 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -44,17 +44,7 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') throw 'Reserve assets is undefined. Check ReserveAssets configuration at config directory'; } - await initReservesByHelper( - lendingPoolProxy.address, - addressesProvider.address, - lendingPoolConfiguratorProxy.address, - ReservesConfig, - reserveAssets, - testHelpers, - admin, - ZERO_ADDRESS, - verify - ); + await initReservesByHelper(ReservesConfig, reserveAssets, admin, ZERO_ADDRESS); await enableReservesToBorrowByHelper(ReservesConfig, reserveAssets, testHelpers, admin); await enableReservesAsCollateralByHelper(ReservesConfig, reserveAssets, testHelpers, admin); diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index 8f27d4d3..4e6f24f8 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -18,6 +18,8 @@ import { deployWalletBalancerProvider, deployAaveProtocolTestHelpers, deployLendingRateOracle, + deployStableAndVariableTokensHelper, + deployATokensAndRatesHelper, } from '../helpers/contracts-deployments'; import {Signer} from 'ethers'; import {TokenContractId, eContractid, tEthereumAddress, AavePools} from '../helpers/types'; @@ -27,8 +29,8 @@ import {initializeMakeSuite} from './helpers/make-suite'; import { setInitialAssetPricesInOracle, - setInitialMarketRatesInRatesOracle, deployAllMockAggregators, + setInitialMarketRatesInRatesOracleByHelper, } from '../helpers/oracles-helpers'; import {waitForTx} from '../helpers/misc-utils'; import { @@ -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 { @@ -207,16 +218,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const admin = await deployer.getAddress(); console.log('Initialize configuration'); - await initReservesByHelper( - lendingPoolProxy.address, - addressesProvider.address, - lendingPoolConfiguratorProxy.address, - reservesParams, - protoPoolReservesAddresses, - testHelpers, - admin, - ZERO_ADDRESS - ); + await initReservesByHelper(reservesParams, protoPoolReservesAddresses, admin, ZERO_ADDRESS); await enableReservesToBorrowByHelper( reservesParams, protoPoolReservesAddresses, @@ -240,7 +242,6 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { await deployWalletBalancerProvider(addressesProvider.address); - console.log('END'); console.timeEnd('setup'); }; From a517d5d11df6e38ce62ce594f428b565d59e3d5a Mon Sep 17 00:00:00 2001 From: David Truong Date: Tue, 27 Oct 2020 13:10:10 +0100 Subject: [PATCH 14/33] - implement test for onBehalfOf flashloan borrow debt --- contracts/interfaces/ILendingPool.sol | 3 + contracts/lendingpool/LendingPool.sol | 14 +++- helpers/types.ts | 1 + test/flashloan.spec.ts | 107 ++++++++++++++++++++++++-- 4 files changed, 117 insertions(+), 8 deletions(-) diff --git a/contracts/interfaces/ILendingPool.sol b/contracts/interfaces/ILendingPool.sol index 4078f511..84a29a57 100644 --- a/contracts/interfaces/ILendingPool.sol +++ b/contracts/interfaces/ILendingPool.sol @@ -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, diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index 6c12b364..04cf84d8 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -503,7 +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 address must already have approved `msg.sender` to incur the debt on their behalf. + * @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 **/ @@ -570,6 +570,16 @@ 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( @@ -585,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); } } diff --git a/helpers/types.ts b/helpers/types.ts index 305ec335..bdd44e11 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -89,6 +89,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 diff --git a/test/flashloan.spec.ts b/test/flashloan.spec.ts index 15f75d61..2538f4fb 100644 --- a/test/flashloan.spec.ts +++ b/test/flashloan.spec.ts @@ -25,6 +25,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 () => { @@ -113,7 +114,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { [weth.address], [ethers.utils.parseEther('0.8')], 0, - _mockFlashLoanReceiver.address, + caller.address, '0x10', '0' ) @@ -134,7 +135,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { [weth.address], [ethers.utils.parseEther('0.8')], 0, - _mockFlashLoanReceiver.address, + caller.address, '0x10', '0' ) @@ -155,7 +156,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { [weth.address], [ethers.utils.parseEther('0.8')], 4, - _mockFlashLoanReceiver.address, + caller.address, '0x10', '0' ) @@ -297,7 +298,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { [usdc.address], [flashloanAmount], 2, - _mockFlashLoanReceiver.address, + caller.address, '0x10', '0' ) @@ -358,7 +359,15 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { await expect( pool .connect(caller.signer) - .flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 0, _mockFlashLoanReceiver.address, '0x10', '0') + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [flashAmount], + 0, + caller.address, + '0x10', + '0' + ) ).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL); }); @@ -373,7 +382,15 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => { await pool .connect(caller.signer) - .flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 1, caller.address, '0x10', '0'); + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [flashAmount], + 1, + caller.address, + '0x10', + '0' + ); const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address); @@ -386,4 +403,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( + eContractid.VariableDebtToken, + stableDebtTokenAddress + ); + + const onBehalfOfDebt = await wethDebtToken.balanceOf(onBehalfOf.address); + + expect(onBehalfOfDebt.toString()).to.be.equal( + '800000000000000000', + 'Invalid onBehalfOf user debt' + ); + }); }); From 87bbfb957144e5adec2b5af851435833eb8773ce Mon Sep 17 00:00:00 2001 From: eboado Date: Tue, 27 Oct 2020 14:42:11 +0100 Subject: [PATCH 15/33] - Changed msg.sender to _msgSender() --- contracts/mocks/tokens/MintableERC20.sol | 2 +- contracts/tokenization/AToken.sol | 4 ++-- contracts/tokenization/IncentivizedERC20.sol | 18 +++++++++--------- contracts/tokenization/base/DebtTokenBase.sol | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/contracts/mocks/tokens/MintableERC20.sol b/contracts/mocks/tokens/MintableERC20.sol index 394bcde2..2c79d971 100644 --- a/contracts/mocks/tokens/MintableERC20.sol +++ b/contracts/mocks/tokens/MintableERC20.sol @@ -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; } } diff --git a/contracts/tokenization/AToken.sol b/contracts/tokenization/AToken.sol index bee1184d..5641ebf8 100644 --- a/contracts/tokenization/AToken.sol +++ b/contracts/tokenization/AToken.sol @@ -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); } /** diff --git a/contracts/tokenization/IncentivizedERC20.sol b/contracts/tokenization/IncentivizedERC20.sol index 771a8202..68b470df 100644 --- a/contracts/tokenization/IncentivizedERC20.sol +++ b/contracts/tokenization/IncentivizedERC20.sol @@ -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 **/ diff --git a/contracts/tokenization/base/DebtTokenBase.sol b/contracts/tokenization/base/DebtTokenBase.sol index fc43e770..0dddb431 100644 --- a/contracts/tokenization/base/DebtTokenBase.sol +++ b/contracts/tokenization/base/DebtTokenBase.sol @@ -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); _; } From bd911de167a2db5faed34a0a6aa1eb6d96169de9 Mon Sep 17 00:00:00 2001 From: emilio Date: Tue, 27 Oct 2020 15:09:11 +0100 Subject: [PATCH 16/33] Fixed ReserveDataUpdated event --- contracts/interfaces/ILendingPool.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/interfaces/ILendingPool.sol b/contracts/interfaces/ILendingPool.sol index 17e75fa6..f44a458a 100644 --- a/contracts/interfaces/ILendingPool.sol +++ b/contracts/interfaces/ILendingPool.sol @@ -162,7 +162,6 @@ interface ILendingPool { address indexed reserve, uint256 liquidityRate, uint256 stableBorrowRate, - uint256 averageStableBorrowRate, uint256 variableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex From 28a63237635dafc304f6219b59d216feed85ba12 Mon Sep 17 00:00:00 2001 From: emilio Date: Tue, 27 Oct 2020 16:57:05 +0100 Subject: [PATCH 17/33] fixed condition, local variable name --- contracts/libraries/logic/GenericLogic.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/libraries/logic/GenericLogic.sol b/contracts/libraries/logic/GenericLogic.sol index a5801b9d..04aab7b2 100644 --- a/contracts/libraries/logic/GenericLogic.sol +++ b/contracts/libraries/logic/GenericLogic.sol @@ -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; } @@ -110,7 +110,7 @@ library GenericLogic { vars.liquidationThresholdAfterDecrease ); - return healthFactorAfterDecrease > GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD; + return healthFactorAfterDecrease >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD; } struct CalculateUserAccountDataVars { From 276dee4918d1b76b236195e674132fa7d4ba2324 Mon Sep 17 00:00:00 2001 From: emilio Date: Tue, 27 Oct 2020 17:22:51 +0100 Subject: [PATCH 18/33] Fixes#87 --- contracts/libraries/logic/ReserveLogic.sol | 18 +- contracts/libraries/math/MathUtils.sol | 25 ++- deployed-contracts.json | 222 ++++++--------------- 3 files changed, 92 insertions(+), 173 deletions(-) diff --git a/contracts/libraries/logic/ReserveLogic.sol b/contracts/libraries/logic/ReserveLogic.sol index ee6749da..1e4cba4c 100644 --- a/contracts/libraries/logic/ReserveLogic.sol +++ b/contracts/libraries/logic/ReserveLogic.sol @@ -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; diff --git a/contracts/libraries/math/MathUtils.sol b/contracts/libraries/math/MathUtils.sol index e929e57c..e99a7ccc 100644 --- a/contracts/libraries/math/MathUtils.sol +++ b/contracts/libraries/math/MathUtils.sol @@ -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); + } } diff --git a/deployed-contracts.json b/deployed-contracts.json index 96e0d9df..d7001b2a 100644 --- a/deployed-contracts.json +++ b/deployed-contracts.json @@ -35,18 +35,6 @@ "buidlerevm": { "address": "0x5A0773Ff307Bf7C71a832dBB5312237fD3437f9F", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "localhost": { - "address": "0xa89E20284Bd638F31b0011D0fC754Fc9d2fa73e3", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "coverage": { - "address": "0x5A0773Ff307Bf7C71a832dBB5312237fD3437f9F", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "kovan": { - "address": "0xf3266d89e6742fAE2C35D05eD549cd4e117300a7", - "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } }, "FeeProvider": { @@ -73,10 +61,16 @@ "address": "0x6642B57e4265BAD868C17Fc1d1F4F88DBBA04Aa8" }, "localhost": { - "address": "0x9Ec55627757348b322c8dD0865D704649bFa0c7b" + "address": "0xaca5aCeB6f44845d07Fd339a51F0bd52Bb3D8D1A", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + }, + "coverage": { + "address": "0xB660Fdd109a95718cB9d20E3A89EE6cE342aDcB6", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "kovan": { - "address": "0x1aae278bCcdb95817c7A546d752fC662F09b6DBa" + "address": "0x0EDc241FdA0dF39EB1B9eB1236217BBe72Ab911D", + "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } }, "LendingPoolDataProvider": { @@ -89,10 +83,14 @@ "address": "0xD9273d497eDBC967F39d419461CfcF382a0A822e" }, "localhost": { - "address": "0x3EE716e38f21e5FC16BFDB773db24D63C637A5d8" + "address": "0x987223924D2DD6c6efB601756850f3886ECbceF6" + }, + "coverage": { + "address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4" }, "kovan": { - "address": "0x8E05A3054cb736258FaF4638D07058cE6e294d2C" + "address": "0xfF28b837352d9531bAb6dFF3650D7831192117F7", + "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } }, "PriceOracle": { @@ -101,11 +99,7 @@ "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { - "address": "0x5889354f21A1C8D8D2f82669d778f6Dab778B519", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "coverage": { - "address": "0x1750499D05Ed1674d822430FB960d5F6731fDf64", + "address": "0x9bD0Bec44106D8Ea8fFb6296d7A84742a290E064", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, @@ -128,16 +122,8 @@ "address": "0x7B6C3e5486D9e6959441ab554A889099eed76290", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, - "localhost": { - "address": "0x0B63c002cb44B2e5e580C3B3560a27F4101D95c0", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "coverage": { - "address": "0x7B6C3e5486D9e6959441ab554A889099eed76290", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, "kovan": { - "address": "0x18a107d4fa249Efefd4DAf9A76EEE3b6366701AA", + "address": "0x293f5BcC66762c28a5d3Bd8512a799D457F5296D", "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } }, @@ -164,16 +150,12 @@ "address": "0xB660Fdd109a95718cB9d20E3A89EE6cE342aDcB6", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, - "localhost": { - "address": "0x7C95b1ad025F0C9aB14192f87bF2aD53889bE4F7", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, "coverage": { - "address": "0x626FdE749F9d499d3777320CAf29484B624ab84a", + "address": "0xA0AB1cB92A4AF81f84dCd258155B5c25D247b54E", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "kovan": { - "address": "0x47341CE48FfE1cbD91991578B880a18c45cdB5CA", + "address": "0xf303Ae6F24C29D94E367fdb5C7aE04D32BEbF13E", "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" } }, @@ -227,10 +209,12 @@ "address": "0xBEF0d4b9c089a5883741fC14cbA352055f35DDA2" }, "localhost": { - "address": "0x9c91aEaD98b1354C7B0EAfb8ff539d0796c79894" + "address": "0x2A7BE996B8801ED21f2f45148791D402811A2106", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "coverage": { - "address": "0x2B681757d757fbB80cc51c6094cEF5eE75bF55aA" + "address": "0xEBAB67ee3ef604D5c250A53b4b8fcbBC6ec3007C", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, "WalletBalanceProvider": { @@ -238,13 +222,11 @@ "address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, - "localhost": { - "address": "0x145b7B6368Df63e7F3497b0A948B30fC1A4d5E55", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, "coverage": { - "address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + "address": "0xBEF0d4b9c089a5883741fC14cbA352055f35DDA2" + }, + "localhost": { + "address": "0x48FAde2E719B770E1783d03466dAEe98b5183538" } }, "DAI": { @@ -565,93 +547,28 @@ "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, - "LendingPoolAddressesProviderRegistry": { - "buidlerevm": { - "address": "0x5A0773Ff307Bf7C71a832dBB5312237fD3437f9F", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - } - }, - "LendingPool": { - "buidlerevm": { - "address": "0xe7536f450378748E1BD4645D3c77ec38e0F3ba28" - }, - "localhost": { - "address": "0x987223924D2DD6c6efB601756850f3886ECbceF6" - }, - "coverage": { - "address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4" - }, - "kovan": { - "address": "0xfF28b837352d9531bAb6dFF3650D7831192117F7", - "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" - } - }, - "LendingPoolConfigurator": { - "buidlerevm": { - "address": "0x830bceA96E56DBC1F8578f75fBaC0AF16B32A07d", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "localhost": { - "address": "0xaca5aCeB6f44845d07Fd339a51F0bd52Bb3D8D1A", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "coverage": { - "address": "0xB660Fdd109a95718cB9d20E3A89EE6cE342aDcB6", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "kovan": { - "address": "0x0EDc241FdA0dF39EB1B9eB1236217BBe72Ab911D", - "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" - } - }, - "PriceOracle": { - "buidlerevm": { - "address": "0x1750499D05Ed1674d822430FB960d5F6731fDf64", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "localhost": { - "address": "0x9bD0Bec44106D8Ea8fFb6296d7A84742a290E064", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - } - }, - "ChainlinkProxyPriceProvider": { - "buidlerevm": { - "address": "0x7B6C3e5486D9e6959441ab554A889099eed76290", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "kovan": { - "address": "0x293f5BcC66762c28a5d3Bd8512a799D457F5296D", - "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" - } - }, "AToken": { + "buidlerevm": { + "address": "0x5f7134cd38C826a7649f9Cc47dda24d834DD2967", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + }, "localhost": { - "address": "0x00f126cCA2266bFb634Ed6DB17c4C74fb8cA5177", + "address": "0x7436d6adaA697413F00cb63E1A2A854bF2Aec5A1", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + }, + "coverage": { + "address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, "AaveProtocolTestHelpers": { "buidlerevm": { - "address": "0x689d0586F88cDEa1E1003F838DD943415E4EB1e5" - } - }, - "DefaultReserveInterestRateStrategy": { - "buidlerevm": { - "address": "0x5f7134cd38C826a7649f9Cc47dda24d834DD2967", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "coverage": { - "address": "0xA0AB1cB92A4AF81f84dCd258155B5c25D247b54E", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "kovan": { - "address": "0xf303Ae6F24C29D94E367fdb5C7aE04D32BEbF13E", - "deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F" + "address": "0xe7536f450378748E1BD4645D3c77ec38e0F3ba28" } }, "StableDebtToken": { "buidlerevm": { - "address": "0x3bDA11B584dDff7F66E0cFe1da1562c92B45db60", + "address": "0x830bceA96E56DBC1F8578f75fBaC0AF16B32A07d", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -665,7 +582,7 @@ }, "VariableDebtToken": { "buidlerevm": { - "address": "0xf784709d2317D872237C4bC22f867d1BAe2913AB", + "address": "0xA0AB1cB92A4AF81f84dCd258155B5c25D247b54E", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" }, "localhost": { @@ -677,45 +594,6 @@ "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, - "AToken": { - "buidlerevm": { - "address": "0x392E5355a0e88Bd394F717227c752670fb3a8020", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "localhost": { - "address": "0x7436d6adaA697413F00cb63E1A2A854bF2Aec5A1", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "coverage": { - "address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - } - }, - "MockFlashLoanReceiver": { - "buidlerevm": { - "address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "localhost": { - "address": "0x2A7BE996B8801ED21f2f45148791D402811A2106", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - }, - "coverage": { - "address": "0xEBAB67ee3ef604D5c250A53b4b8fcbBC6ec3007C", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" - } - }, - "WalletBalanceProvider": { - "buidlerevm": { - "address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10" - }, - "coverage": { - "address": "0xBEF0d4b9c089a5883741fC14cbA352055f35DDA2" - }, - "localhost": { - "address": "0x48FAde2E719B770E1783d03466dAEe98b5183538" - } - }, "MockFlashRepayAdapter": { "buidlerevm": { "address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10" @@ -725,5 +603,29 @@ "buidlerevm": { "address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4" } + }, + "WETH": { + "buidlerevm": { + "address": "0xf784709d2317D872237C4bC22f867d1BAe2913AB", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + } + }, + "MockAToken": { + "buidlerevm": { + "address": "0x3bDA11B584dDff7F66E0cFe1da1562c92B45db60", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + } + }, + "MockStableDebtToken": { + "buidlerevm": { + "address": "0x392E5355a0e88Bd394F717227c752670fb3a8020", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + } + }, + "MockVariableDebtToken": { + "buidlerevm": { + "address": "0x3b050AFb4ac4ACE646b31fF3639C1CD43aC31460", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + } } } From 1cd7f2d5a0b0b063ed9423334f352152b7fd359a Mon Sep 17 00:00:00 2001 From: emilio Date: Tue, 27 Oct 2020 17:49:35 +0100 Subject: [PATCH 19/33] Fixed error on variable naming --- contracts/libraries/logic/GenericLogic.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/libraries/logic/GenericLogic.sol b/contracts/libraries/logic/GenericLogic.sol index 04aab7b2..28d91927 100644 --- a/contracts/libraries/logic/GenericLogic.sol +++ b/contracts/libraries/logic/GenericLogic.sol @@ -102,10 +102,10 @@ 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 ); From 6be8b1c5fdbe37d641453c27a61864d029753f23 Mon Sep 17 00:00:00 2001 From: eboado Date: Wed, 28 Oct 2020 10:54:09 +0100 Subject: [PATCH 20/33] - Added validations on ReserveConfiguration's numeric setters. --- .../configuration/ReserveConfiguration.sol | 21 ++++++- contracts/libraries/helpers/Errors.sol | 9 +++ helpers/types.ts | 6 ++ test/configurator.spec.ts | 58 ++++++++++++++++++- 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/contracts/libraries/configuration/ReserveConfiguration.sol b/contracts/libraries/configuration/ReserveConfiguration.sol index 553cec66..ccef1e00 100644 --- a/contracts/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/libraries/configuration/ReserveConfiguration.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: agpl-3.0 pragma solidity ^0.6.8; +import {Errors} from '../helpers/Errors.sol'; + /** * @title ReserveConfiguration library * @author Aave @@ -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); } @@ -225,6 +241,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); @@ -316,8 +334,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 diff --git a/contracts/libraries/helpers/Errors.sol b/contracts/libraries/helpers/Errors.sol index 91dd385f..9ed7b07e 100644 --- a/contracts/libraries/helpers/Errors.sol +++ b/contracts/libraries/helpers/Errors.sol @@ -89,6 +89,15 @@ 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, diff --git a/helpers/types.ts b/helpers/types.ts index 305ec335..944c2be0 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -117,6 +117,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', diff --git a/test/configurator.spec.ts b/test/configurator.spec.ts index 891c88dc..788add5c 100644 --- a/test/configurator.spec.ts +++ b/test/configurator.spec.ts @@ -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; From 245077a6eb60b85a9e6add2bffed84c609ad2733 Mon Sep 17 00:00:00 2001 From: emilio Date: Wed, 28 Oct 2020 10:54:20 +0100 Subject: [PATCH 21/33] Updated gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 03a9d01b..626ee868 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,10 @@ build/ .idea types +deployed-contracts.json + coverage .coverage_artifacts .coverage_cache .coverage_contracts + From 13737e09947e9e20bc99eff6f517ed4a938c3168 Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 28 Oct 2020 11:27:16 +0100 Subject: [PATCH 22/33] Show WETH instead of ETH --- helpers/init-helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 61751052..b33e3b9a 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -78,7 +78,7 @@ export const initReservesByHelper = async ( ] = (Object.entries(reservesParams) as [string, IReserveParams][])[reserveParamIndex]; // Add to lists tokens.push(tokenAddress); - symbols.push(assetSymbol === 'WETH' ? 'ETH' : assetSymbol); + symbols.push(assetSymbol); strategyRates.push([ baseVariableBorrowRate, variableRateSlope1, From 064af06385742d510e872d4e75d955ae1377e8d8 Mon Sep 17 00:00:00 2001 From: emilio Date: Wed, 28 Oct 2020 11:47:01 +0100 Subject: [PATCH 23/33] updated percentageMath --- contracts/libraries/math/WadRayMath.sol | 29 +++++++++---------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/contracts/libraries/math/WadRayMath.sol b/contracts/libraries/math/WadRayMath.sol index a1a8d8f4..48985580 100644 --- a/contracts/libraries/math/WadRayMath.sol +++ b/contracts/libraries/math/WadRayMath.sol @@ -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,14 @@ 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 (a * b + halfRAY) / RAY; - return result / RAY; } /** @@ -109,14 +103,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; } /** From a9a863fcb468ab757a94ab99ef44c0170b541727 Mon Sep 17 00:00:00 2001 From: eboado Date: Wed, 28 Oct 2020 11:56:10 +0100 Subject: [PATCH 24/33] - Fixes misc comments on LendingPoolAddressesProviderRegistry. --- .../configuration/LendingPoolAddressesProviderRegistry.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/configuration/LendingPoolAddressesProviderRegistry.sol b/contracts/configuration/LendingPoolAddressesProviderRegistry.sol index 53ef4d10..bf15ef3d 100644 --- a/contracts/configuration/LendingPoolAddressesProviderRegistry.sol +++ b/contracts/configuration/LendingPoolAddressesProviderRegistry.sol @@ -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 From 232743c332f9db6b4ee0f0e95e459eb2bff75b02 Mon Sep 17 00:00:00 2001 From: eboado Date: Wed, 28 Oct 2020 12:02:40 +0100 Subject: [PATCH 25/33] - Cached _reservesCount on _addReserveToList() --- contracts/lendingpool/LendingPool.sol | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index c63ff348..3f490365 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -913,13 +913,16 @@ 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++; } From e91e3595d6c5e82d294e15f3ca2225730ad581f7 Mon Sep 17 00:00:00 2001 From: emilio Date: Wed, 28 Oct 2020 12:39:11 +0100 Subject: [PATCH 26/33] Updated PercentageMath --- contracts/libraries/math/PercentageMath.sol | 22 +++++---------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/contracts/libraries/math/PercentageMath.sol b/contracts/libraries/math/PercentageMath.sol index b853f1db..52a38cd4 100644 --- a/contracts/libraries/math/PercentageMath.sol +++ b/contracts/libraries/math/PercentageMath.sol @@ -22,19 +22,13 @@ 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 +41,8 @@ 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; } } From 1ef1f614bd16632f8846721256700bd32f2f93cf Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 28 Oct 2020 18:13:31 +0100 Subject: [PATCH 27/33] Remove extra whitespace --- contracts/deployments/StableAndVariableTokensHelper.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/deployments/StableAndVariableTokensHelper.sol b/contracts/deployments/StableAndVariableTokensHelper.sol index c104758f..54d6ffcb 100644 --- a/contracts/deployments/StableAndVariableTokensHelper.sol +++ b/contracts/deployments/StableAndVariableTokensHelper.sol @@ -18,7 +18,7 @@ contract StableAndVariableTokensHelper is Ownable { } function concat(string memory a, string memory b) internal pure returns (string memory) { - return string(abi.encodePacked(a, ' ', b)); + return string(abi.encodePacked(a, b)); } function initDeployment( From a966d9f53f1262a186cbcbb313648b0ec2794965 Mon Sep 17 00:00:00 2001 From: David Racero Date: Wed, 28 Oct 2020 18:39:19 +0100 Subject: [PATCH 28/33] Added new StringLib library with concat to reuse function in deployment helpers. --- .../deployments/ATokensAndRatesHelper.sol | 9 +++---- .../StableAndVariableTokensHelper.sol | 13 ++++----- contracts/libraries/helpers/StringLib.sol | 8 ++++++ deployed-contracts.json | 27 +++++++++++++++---- package.json | 1 + test/atoken-transfer.spec.ts | 4 +++ test/stable-token.spec.ts | 3 +++ 7 files changed, 46 insertions(+), 19 deletions(-) create mode 100644 contracts/libraries/helpers/StringLib.sol diff --git a/contracts/deployments/ATokensAndRatesHelper.sol b/contracts/deployments/ATokensAndRatesHelper.sol index 83146959..769b98fc 100644 --- a/contracts/deployments/ATokensAndRatesHelper.sol +++ b/contracts/deployments/ATokensAndRatesHelper.sol @@ -10,6 +10,7 @@ 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; @@ -27,10 +28,6 @@ contract ATokensAndRatesHelper is Ownable { poolConfigurator = _poolConfigurator; } - function concat(string memory a, string memory b) internal pure returns (string memory) { - return string(abi.encodePacked(a, b)); - } - function initDeployment( address[] calldata tokens, string[] calldata symbols, @@ -47,8 +44,8 @@ contract ATokensAndRatesHelper is Ownable { LendingPool(pool), tokens[i], address(0), - concat('Aave interest bearing ', symbols[i]), - concat('a', symbols[i]), + StringLib.concat('Aave interest bearing ', symbols[i]), + StringLib.concat('a', symbols[i]), incentivesController ) ), diff --git a/contracts/deployments/StableAndVariableTokensHelper.sol b/contracts/deployments/StableAndVariableTokensHelper.sol index 54d6ffcb..9722424e 100644 --- a/contracts/deployments/StableAndVariableTokensHelper.sol +++ b/contracts/deployments/StableAndVariableTokensHelper.sol @@ -6,6 +6,7 @@ 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; @@ -17,10 +18,6 @@ contract StableAndVariableTokensHelper is Ownable { addressesProvider = _addressesProvider; } - function concat(string memory a, string memory b) internal pure returns (string memory) { - return string(abi.encodePacked(a, b)); - } - function initDeployment( address[] calldata tokens, string[] calldata symbols, @@ -34,8 +31,8 @@ contract StableAndVariableTokensHelper is Ownable { new StableDebtToken( pool, tokens[i], - concat('Aave stable debt bearing ', symbols[i]), - concat('stableDebt', symbols[i]), + StringLib.concat('Aave stable debt bearing ', symbols[i]), + StringLib.concat('stableDebt', symbols[i]), incentivesController ) ), @@ -43,8 +40,8 @@ contract StableAndVariableTokensHelper is Ownable { new VariableDebtToken( pool, tokens[i], - concat('Aave variable debt bearing ', symbols[i]), - concat('variableDebt', symbols[i]), + StringLib.concat('Aave variable debt bearing ', symbols[i]), + StringLib.concat('variableDebt', symbols[i]), incentivesController ) ) diff --git a/contracts/libraries/helpers/StringLib.sol b/contracts/libraries/helpers/StringLib.sol new file mode 100644 index 00000000..fd4584a0 --- /dev/null +++ b/contracts/libraries/helpers/StringLib.sol @@ -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)); + } +} diff --git a/deployed-contracts.json b/deployed-contracts.json index ef612b08..642cd6a5 100644 --- a/deployed-contracts.json +++ b/deployed-contracts.json @@ -163,26 +163,25 @@ }, "ReserveLogic": { "buidlerevm": { - "address": "0x78Ee8Fb9fE5abD5e347Fc94c2fb85596d1f60e3c", + "address": "0xFAe0fd738dAbc8a0426F47437322b6d026A9FD95", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, "GenericLogic": { "buidlerevm": { - "address": "0x920d847fE49E54C19047ba8bc236C45A8068Bca7", + "address": "0x6082731fdAba4761277Fb31299ebC782AD3bCf24", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, "ValidationLogic": { "buidlerevm": { - "address": "0xA4765Ff72A9F3CfE73089bb2c3a41B838DF71574", + "address": "0x8456161947DFc1fC159A0B26c025cD2b4bba0c3e", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } }, "LendingPool": { "buidlerevm": { - "address": "0x35c1419Da7cf0Ff885B8Ef8EA9242FEF6800c99b", - "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + "address": "0xD9273d497eDBC967F39d419461CfcF382a0A822e" } }, "LendingPoolConfigurator": { @@ -247,5 +246,23 @@ "address": "0x1256eBA4d0a7A38D10BaF4F61775ba491Ce7EE25", "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } + }, + "MockAToken": { + "buidlerevm": { + "address": "0x77B0b5636fEA30eA79BB65AeCCdb599997A849A8", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + } + }, + "MockStableDebtToken": { + "buidlerevm": { + "address": "0x78Ee8Fb9fE5abD5e347Fc94c2fb85596d1f60e3c", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + } + }, + "MockVariableDebtToken": { + "buidlerevm": { + "address": "0x920d847fE49E54C19047ba8bc236C45A8068Bca7", + "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" + } } } diff --git a/package.json b/package.json index fd75fdb8..931b1186 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "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", diff --git a/test/atoken-transfer.spec.ts b/test/atoken-transfer.spec.ts index 0e207e17..10bf15d4 100644 --- a/test/atoken-transfer.spec.ts +++ b/test/atoken-transfer.spec.ts @@ -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); diff --git a/test/stable-token.spec.ts b/test/stable-token.spec.ts index 422cb352..fea265c6 100644 --- a/test/stable-token.spec.ts +++ b/test/stable-token.spec.ts @@ -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 ); From 9e55ea12b67f20b7e762e027e8048cbb5f38e147 Mon Sep 17 00:00:00 2001 From: emilio Date: Thu, 29 Oct 2020 11:57:43 +0100 Subject: [PATCH 29/33] Fixes #99 --- contracts/interfaces/ILendingPool.sol | 13 +++-- contracts/lendingpool/LendingPool.sol | 54 ++++++++++++------- contracts/libraries/logic/ValidationLogic.sol | 40 ++++++++++++++ contracts/tokenization/AToken.sol | 28 +++++----- contracts/tokenization/interfaces/IAToken.sol | 2 - deployed-contracts.json | 2 +- test/atoken-transfer.spec.ts | 47 ++++++++-------- 7 files changed, 123 insertions(+), 63 deletions(-) diff --git a/contracts/interfaces/ILendingPool.sol b/contracts/interfaces/ILendingPool.sol index f44a458a..b893c16b 100644 --- a/contracts/interfaces/ILendingPool.sol +++ b/contracts/interfaces/ILendingPool.sol @@ -349,11 +349,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); diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index 3f490365..fde9d760 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -724,29 +724,46 @@ 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() - ); + + 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) { + UserConfiguration.Map storage toConfig = _usersConfig[to]; + toConfig.setUsingAsCollateral(reserveId, true); + } + } } /** @@ -913,7 +930,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage * @dev adds a reserve to the array of the _reserves address **/ function _addReserveToList(address asset) internal { - uint256 reservesCount = _reservesCount; require(reservesCount < MAX_NUMBER_RESERVES, Errors.NO_MORE_RESERVES_ALLOWED); diff --git a/contracts/libraries/logic/ValidationLogic.sol b/contracts/libraries/logic/ValidationLogic.sol index 947d84ea..c772e307 100644 --- a/contracts/libraries/logic/ValidationLogic.sol +++ b/contracts/libraries/logic/ValidationLogic.sol @@ -13,6 +13,8 @@ import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol'; import {UserConfiguration} from '../configuration/UserConfiguration.sol'; import {Errors} from '../helpers/Errors.sol'; import {Helpers} from '../helpers/Helpers.sol'; +import "@nomiclabs/buidler/console.sol"; + /** * @title ReserveLogic library @@ -46,6 +48,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 +396,37 @@ 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 + ); + + console.log("Health factor after transfer %s", healthFactor); + + require( + healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD, + Errors.TRANSFER_NOT_ALLOWED + ); + } } diff --git a/contracts/tokenization/AToken.sol b/contracts/tokenization/AToken.sol index 5641ebf8..adc1771b 100644 --- a/contracts/tokenization/AToken.sol +++ b/contracts/tokenization/AToken.sol @@ -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); } diff --git a/contracts/tokenization/interfaces/IAToken.sol b/contracts/tokenization/interfaces/IAToken.sol index 00f63b20..055e3f5d 100644 --- a/contracts/tokenization/interfaces/IAToken.sol +++ b/contracts/tokenization/interfaces/IAToken.sol @@ -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 diff --git a/deployed-contracts.json b/deployed-contracts.json index d7001b2a..4b961b6c 100644 --- a/deployed-contracts.json +++ b/deployed-contracts.json @@ -628,4 +628,4 @@ "deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6" } } -} +} \ No newline at end of file diff --git a/test/atoken-transfer.spec.ts b/test/atoken-transfer.spec.ts index 0e207e17..89ed584f 100644 --- a/test/atoken-transfer.spec.ts +++ b/test/atoken-transfer.spec.ts @@ -46,8 +46,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 +57,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 +67,32 @@ 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()); + }); }); From 2cf84f19ce43626b3ff854bf8269ddf39018fe2c Mon Sep 17 00:00:00 2001 From: emilio Date: Thu, 29 Oct 2020 12:03:26 +0100 Subject: [PATCH 30/33] removed console import --- contracts/libraries/logic/ValidationLogic.sol | 4 ---- 1 file changed, 4 deletions(-) diff --git a/contracts/libraries/logic/ValidationLogic.sol b/contracts/libraries/logic/ValidationLogic.sol index c772e307..78f74154 100644 --- a/contracts/libraries/logic/ValidationLogic.sol +++ b/contracts/libraries/logic/ValidationLogic.sol @@ -13,8 +13,6 @@ import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol'; import {UserConfiguration} from '../configuration/UserConfiguration.sol'; import {Errors} from '../helpers/Errors.sol'; import {Helpers} from '../helpers/Helpers.sol'; -import "@nomiclabs/buidler/console.sol"; - /** * @title ReserveLogic library @@ -422,8 +420,6 @@ library ValidationLogic { oracle ); - console.log("Health factor after transfer %s", healthFactor); - require( healthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD, Errors.TRANSFER_NOT_ALLOWED From 6cd18c4320dd072e9ac77bfb4528ef48bd345df1 Mon Sep 17 00:00:00 2001 From: eboado Date: Thu, 29 Oct 2020 12:09:07 +0100 Subject: [PATCH 31/33] - Simplified getter of boolean fields on ReserveConfiguration. - Added all 256 bits to masks on ReserveConfiguration for clarity. --- .../configuration/ReserveConfiguration.sol | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/contracts/libraries/configuration/ReserveConfiguration.sol b/contracts/libraries/configuration/ReserveConfiguration.sol index ccef1e00..ce4f722a 100644 --- a/contracts/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/libraries/configuration/ReserveConfiguration.sol @@ -9,15 +9,15 @@ import {Errors} from '../helpers/Errors.sol'; * @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; @@ -161,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; } /** @@ -181,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; } /** @@ -201,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; } /** @@ -228,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; } /** @@ -275,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 ); } @@ -350,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 ); } } From 3f7d913fd43020328c827db4f5e045c9ce59c6b4 Mon Sep 17 00:00:00 2001 From: emilio Date: Thu, 29 Oct 2020 13:43:24 +0100 Subject: [PATCH 32/33] Fixed issue on 0 transfer, added check that the caller must be an aToken --- contracts/lendingpool/LendingPool.sol | 4 +++- contracts/libraries/helpers/Errors.sol | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index fde9d760..1684247e 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -742,6 +742,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage ) external override { _whenNotPaused(); + require(msg.sender == _reserves[asset].aTokenAddress, Errors.CALLER_MUST_BE_AN_ATOKEN); + ValidationLogic.validateTransfer( from, _reserves, @@ -759,7 +761,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage fromConfig.setUsingAsCollateral(reserveId, false); } - if (balanceToBefore == 0) { + if (balanceToBefore == 0 && amount != 0) { UserConfiguration.Map storage toConfig = _usersConfig[to]; toConfig.setUsingAsCollateral(reserveId, true); } diff --git a/contracts/libraries/helpers/Errors.sol b/contracts/libraries/helpers/Errors.sol index 9ed7b07e..b515603f 100644 --- a/contracts/libraries/helpers/Errors.sol +++ b/contracts/libraries/helpers/Errors.sol @@ -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' From d373b9beb88a8504a761c81a862c315897e3f0b8 Mon Sep 17 00:00:00 2001 From: David Truong Date: Thu, 29 Oct 2020 15:53:38 +0100 Subject: [PATCH 33/33] Fix for pausable-function flashloan test --- test/pausable-functions.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pausable-functions.spec.ts b/test/pausable-functions.spec.ts index 48c50ee2..e15f2a90 100644 --- a/test/pausable-functions.spec.ts +++ b/test/pausable-functions.spec.ts @@ -186,7 +186,7 @@ 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