From 1c26eeef877f3b7d3f6044f1da96d2577657fcaf Mon Sep 17 00:00:00 2001 From: David Racero Date: Thu, 19 Nov 2020 17:46:23 +0100 Subject: [PATCH 1/4] Add UNI aDelegatedToken --- helpers/init-helpers.ts | 74 ++++++++++++++++++++++++++++++++++++-- tasks/dev/5_initialize.ts | 29 +++++++++------ tasks/full/5_initialize.ts | 22 ++++++------ 3 files changed, 102 insertions(+), 23 deletions(-) diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 35de7ac9..2f04d30a 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -8,17 +8,26 @@ import { } from './contracts-getters'; import { rawInsertContractAddressInDb } from './contracts-helpers'; import { BigNumberish } from 'ethers'; +import { + deployDefaultReserveInterestRateStrategy, + deployDelegationAwareAToken, + deployStableDebtToken, + deployVariableDebtToken, +} from './contracts-deployments'; +import { ZERO_ADDRESS } from './constants'; export const initReservesByHelper = async ( reservesParams: iMultiPoolsAssets, tokenAddresses: { [symbol: string]: tEthereumAddress }, admin: tEthereumAddress, - incentivesController: tEthereumAddress + incentivesController: tEthereumAddress, + verify: boolean ) => { const stableAndVariableDeployer = await getStableAndVariableTokensHelper(); const atokenAndRatesDeployer = await getATokensAndRatesHelper(); const addressProvider = await getLendingPoolAddressesProvider(); + const poolAddress = await addressProvider.getLendingPool(); // Set aTokenAndRatesDeployer as temporal admin await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address)); @@ -39,6 +48,7 @@ export const initReservesByHelper = async ( let deployedRates: string[] = []; let reserveTokens: string[] = []; let reserveInitDecimals: string[] = []; + let reserveSymbols: string[] = []; console.log( `- Token deployments in ${reservesChunks.length * 2} txs instead of ${ @@ -59,6 +69,10 @@ export const initReservesByHelper = async ( const reservesDecimals: string[] = []; for (let [assetSymbol, { reserveDecimals }] of reservesChunk) { + // Skip UNI due is aDelegatedToken + if (assetSymbol === 'UNI') { + continue; + } const assetAddressIndex = Object.keys(tokenAddresses).findIndex( (value) => value === assetSymbol ); @@ -126,6 +140,62 @@ export const initReservesByHelper = async ( deployedRates = [...deployedRates, ...strategies]; reserveInitDecimals = [...reserveInitDecimals, ...reservesDecimals]; reserveTokens = [...reserveTokens, ...tokens]; + reserveSymbols = [...reserveSymbols, ...symbols]; + } + + // Deploy UNI token due is delegated aToken + if (tokenAddresses.UNI) { + console.log(' - Deploy UNI delegated aToken, debts tokens, and strategy'); + const { + baseVariableBorrowRate, + variableRateSlope1, + variableRateSlope2, + stableRateSlope1, + stableRateSlope2, + } = reservesParams.UNI; + const aTokenUNI = await deployDelegationAwareAToken( + [poolAddress, tokenAddresses.UNI, 'Aave interest bearing ', 'aUNI', ZERO_ADDRESS], + verify + ); + const stableDebtUNI = await deployStableDebtToken( + [ + poolAddress, + tokenAddresses.UNI, + 'Aave stable debt bearing UNI', + 'stableDebtUNI', + ZERO_ADDRESS, + ], + verify + ); + const variableDebtUNI = await deployVariableDebtToken( + [ + poolAddress, + tokenAddresses.UNI, + 'Aave variable debt bearing UNI', + 'variableDebtUNI', + ZERO_ADDRESS, + ], + verify + ); + const ratesUNI = await deployDefaultReserveInterestRateStrategy( + [ + tokenAddresses.UNI, + baseVariableBorrowRate, + variableRateSlope1, + variableRateSlope2, + stableRateSlope1, + stableRateSlope2, + ], + verify + ); + + deployedStableTokens.push(stableDebtUNI.address); + deployedVariableTokens.push(variableDebtUNI.address); + deployedATokens.push(aTokenUNI.address); + deployedRates.push(ratesUNI.address); + reserveInitDecimals.push(reservesParams.UNI.reserveDecimals); + reserveTokens.push(tokenAddresses.UNI); + reserveSymbols.push('UNI'); } // Deploy init reserves per chunks @@ -134,7 +204,7 @@ export const initReservesByHelper = async ( const chunkedAtokens = chunk(deployedATokens, initChunks); const chunkedRates = chunk(deployedRates, initChunks); const chunkedDecimals = chunk(reserveInitDecimals, initChunks); - const chunkedSymbols = chunk(Object.keys(tokenAddresses), initChunks); + const chunkedSymbols = chunk(reserveSymbols, initChunks); console.log(`- Reserves initialization in ${chunkedStableTokens.length} txs`); for (let chunkIndex = 0; chunkIndex < chunkedDecimals.length; chunkIndex++) { diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index 11d25729..806ac13e 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -1,4 +1,4 @@ -import {task} from 'hardhat/config'; +import { task } from 'hardhat/config'; import { deployLendingPoolCollateralManager, deployMockFlashLoanReceiver, @@ -13,22 +13,25 @@ import { loadPoolConfig, } from '../../helpers/configuration'; -import {tEthereumAddress, AavePools, eContractid} from '../../helpers/types'; -import {waitForTx, filterMapBy} from '../../helpers/misc-utils'; +import { tEthereumAddress, AavePools, eContractid } from '../../helpers/types'; +import { waitForTx, filterMapBy } from '../../helpers/misc-utils'; import { enableReservesToBorrowByHelper, enableReservesAsCollateralByHelper, initReservesByHelper, } from '../../helpers/init-helpers'; -import {getAllTokenAddresses} from '../../helpers/mock-helpers'; -import {ZERO_ADDRESS} from '../../helpers/constants'; -import {getAllMockedTokens, getLendingPoolAddressesProvider} from '../../helpers/contracts-getters'; -import {insertContractAddressInDb} from '../../helpers/contracts-helpers'; +import { getAllTokenAddresses } from '../../helpers/mock-helpers'; +import { ZERO_ADDRESS } from '../../helpers/constants'; +import { + getAllMockedTokens, + getLendingPoolAddressesProvider, +} from '../../helpers/contracts-getters'; +import { insertContractAddressInDb } from '../../helpers/contracts-helpers'; task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') .addFlag('verify', 'Verify contracts at Etherscan') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) - .setAction(async ({verify, pool}, localBRE) => { + .setAction(async ({ verify, pool }, localBRE) => { await localBRE.run('set-DRE'); const poolConfig = loadPoolConfig(pool); @@ -37,7 +40,7 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') const addressesProvider = await getLendingPoolAddressesProvider(); - const protoPoolReservesAddresses = <{[symbol: string]: tEthereumAddress}>( + const protoPoolReservesAddresses = <{ [symbol: string]: tEthereumAddress }>( filterMapBy(allTokenAddresses, (key: string) => !key.includes('UNI_')) ); @@ -47,7 +50,13 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') const admin = await addressesProvider.getPoolAdmin(); - await initReservesByHelper(reservesParams, protoPoolReservesAddresses, admin, ZERO_ADDRESS); + await initReservesByHelper( + reservesParams, + protoPoolReservesAddresses, + admin, + ZERO_ADDRESS, + verify + ); await enableReservesToBorrowByHelper( reservesParams, protoPoolReservesAddresses, diff --git a/tasks/full/5_initialize.ts b/tasks/full/5_initialize.ts index 99b55f15..64307500 100644 --- a/tasks/full/5_initialize.ts +++ b/tasks/full/5_initialize.ts @@ -1,32 +1,32 @@ -import {task} from 'hardhat/config'; -import {getParamPerNetwork} from '../../helpers/contracts-helpers'; +import { task } from 'hardhat/config'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { deployLendingPoolCollateralManager, deployWalletBalancerProvider, deployAaveProtocolDataProvider, deployWETHGateway, } from '../../helpers/contracts-deployments'; -import {loadPoolConfig, ConfigNames, getWethAddress} from '../../helpers/configuration'; -import {eEthereumNetwork, ICommonConfiguration} from '../../helpers/types'; -import {waitForTx} from '../../helpers/misc-utils'; +import { loadPoolConfig, ConfigNames, getWethAddress } from '../../helpers/configuration'; +import { eEthereumNetwork, ICommonConfiguration } from '../../helpers/types'; +import { waitForTx } from '../../helpers/misc-utils'; import { initReservesByHelper, enableReservesToBorrowByHelper, enableReservesAsCollateralByHelper, } from '../../helpers/init-helpers'; -import {exit} from 'process'; -import {getLendingPoolAddressesProvider} from '../../helpers/contracts-getters'; -import {ZERO_ADDRESS} from '../../helpers/constants'; +import { exit } from 'process'; +import { 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') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) - .setAction(async ({verify, pool}, localBRE) => { + .setAction(async ({ verify, pool }, localBRE) => { try { await localBRE.run('set-DRE'); const network = localBRE.network.name; const poolConfig = loadPoolConfig(pool); - const {ReserveAssets, ReservesConfig} = poolConfig as ICommonConfiguration; + const { ReserveAssets, ReservesConfig } = poolConfig as ICommonConfiguration; const reserveAssets = await getParamPerNetwork(ReserveAssets, network); @@ -39,7 +39,7 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') throw 'Reserve assets is undefined. Check ReserveAssets configuration at config directory'; } - await initReservesByHelper(ReservesConfig, reserveAssets, admin, ZERO_ADDRESS); + await initReservesByHelper(ReservesConfig, reserveAssets, admin, ZERO_ADDRESS, verify); await enableReservesToBorrowByHelper(ReservesConfig, reserveAssets, testHelpers, admin); await enableReservesAsCollateralByHelper(ReservesConfig, reserveAssets, testHelpers, admin); From 39dcb51feeacab467b78e1021e6d638b23940ed3 Mon Sep 17 00:00:00 2001 From: David Racero Date: Thu, 19 Nov 2020 17:47:56 +0100 Subject: [PATCH 2/4] Add missing symbol in name. --- 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 2f04d30a..28e1bdca 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -154,7 +154,7 @@ export const initReservesByHelper = async ( stableRateSlope2, } = reservesParams.UNI; const aTokenUNI = await deployDelegationAwareAToken( - [poolAddress, tokenAddresses.UNI, 'Aave interest bearing ', 'aUNI', ZERO_ADDRESS], + [poolAddress, tokenAddresses.UNI, 'Aave interest bearing UNI', 'aUNI', ZERO_ADDRESS], verify ); const stableDebtUNI = await deployStableDebtToken( From e04c7092fc3e7ca1b45c1542214755be009f6b7f Mon Sep 17 00:00:00 2001 From: David Racero Date: Fri, 20 Nov 2020 10:57:52 +0100 Subject: [PATCH 3/4] Change wrong ID from deployment scripts --- helpers/contracts-deployments.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 4ca6cede..1244a6fa 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -366,7 +366,7 @@ export const deployDelegationAwareAToken = async ( ] = [poolAddress, underlyingAssetAddress, ZERO_ADDRESS, name, symbol, incentivesController]; return withSaveAndVerify( await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(...args), - eContractid.AToken, + eContractid.DelegationAwareAToken, args, verify ); From 4034c755361143388c752961215870664a36269b Mon Sep 17 00:00:00 2001 From: David Racero Date: Fri, 20 Nov 2020 12:11:57 +0100 Subject: [PATCH 4/4] Support custom aToken deployments --- helpers/contracts-deployments.ts | 2 +- helpers/init-helpers.ts | 87 ++++++++++++++++++++------------ helpers/types.ts | 4 +- markets/aave/reservesConfigs.ts | 11 +++- 4 files changed, 68 insertions(+), 36 deletions(-) diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 1244a6fa..40a8c660 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -288,7 +288,7 @@ export const deployMintableDelegationERC20 = async ( verify ); export const deployDefaultReserveInterestRateStrategy = async ( - args: [tEthereumAddress, string, string, string, string, string], + args: [tEthereumAddress, string, string, string, string, string, string], verify: boolean ) => withSaveAndVerify( diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index 494c6e3f..a426274c 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -1,4 +1,4 @@ -import { iMultiPoolsAssets, IReserveParams, tEthereumAddress } from './types'; +import { eContractid, iMultiPoolsAssets, IReserveParams, tEthereumAddress } from './types'; import { AaveProtocolDataProvider } from '../types/AaveProtocolDataProvider'; import { chunk, waitForTx } from './misc-utils'; import { @@ -11,11 +11,23 @@ import { BigNumberish } from 'ethers'; import { deployDefaultReserveInterestRateStrategy, deployDelegationAwareAToken, + deployGenericAToken, deployStableDebtToken, deployVariableDebtToken, } from './contracts-deployments'; import { ZERO_ADDRESS } from './constants'; +const chooseATokenDeployment = (id: eContractid) => { + switch (id) { + case eContractid.AToken: + return deployGenericAToken; + case eContractid.DelegationAwareAToken: + return deployDelegationAwareAToken; + default: + throw Error(`Missing aToken deployment script for: ${id}`); + } +}; + export const initReservesByHelper = async ( reservesParams: iMultiPoolsAssets, tokenAddresses: { [symbol: string]: tEthereumAddress }, @@ -36,9 +48,11 @@ export const initReservesByHelper = async ( const tokensChunks = 4; const initChunks = 6; - // Deploy tokens and rates in chunks + // Deploy tokens and rates that uses common aToken in chunks const reservesChunks = chunk( - Object.entries(reservesParams) as [string, IReserveParams][], + Object.entries(reservesParams).filter( + ([_, { aTokenImpl }]) => aTokenImpl === eContractid.AToken + ) as [string, IReserveParams][], tokensChunks ); // Initialize variables for future reserves initialization @@ -70,10 +84,6 @@ export const initReservesByHelper = async ( const reservesDecimals: string[] = []; for (let [assetSymbol, { reserveDecimals }] of reservesChunk) { - // Skip UNI due is aDelegatedToken - if (assetSymbol === 'UNI') { - continue; - } const assetAddressIndex = Object.keys(tokenAddresses).findIndex( (value) => value === assetSymbol ); @@ -146,43 +156,56 @@ export const initReservesByHelper = async ( reserveSymbols = [...reserveSymbols, ...symbols]; } - // Deploy UNI token due is delegated aToken - if (tokenAddresses.UNI) { - console.log(' - Deploy UNI delegated aToken, debts tokens, and strategy'); + // Deploy delegated aware reserves tokens + const delegatedAwareReserves = Object.entries(reservesParams).filter( + ([_, { aTokenImpl }]) => aTokenImpl === eContractid.DelegationAwareAToken + ) as [string, IReserveParams][]; + + for (let [symbol, params] of delegatedAwareReserves) { + console.log(` - Deploy ${symbol} delegation await aToken, debts tokens, and strategy`); const { + optimalUtilizationRate, baseVariableBorrowRate, variableRateSlope1, variableRateSlope2, stableRateSlope1, stableRateSlope2, - } = reservesParams.UNI; - const aTokenUNI = await deployDelegationAwareAToken( - [poolAddress, tokenAddresses.UNI, 'Aave interest bearing UNI', 'aUNI', ZERO_ADDRESS], - verify - ); - const stableDebtUNI = await deployStableDebtToken( + } = params; + const deployCustomAToken = chooseATokenDeployment(params.aTokenImpl); + const aToken = await deployCustomAToken( [ poolAddress, - tokenAddresses.UNI, - 'Aave stable debt bearing UNI', - 'stableDebtUNI', + tokenAddresses[symbol], + `Aave interest bearing ${symbol}`, + `a${symbol}`, ZERO_ADDRESS, ], verify ); - const variableDebtUNI = await deployVariableDebtToken( + const stableDebt = await deployStableDebtToken( [ poolAddress, - tokenAddresses.UNI, - 'Aave variable debt bearing UNI', - 'variableDebtUNI', + tokenAddresses[symbol], + `Aave stable debt bearing ${symbol}`, + `stableDebt${symbol}`, ZERO_ADDRESS, ], verify ); - const ratesUNI = await deployDefaultReserveInterestRateStrategy( + const variableDebt = await deployVariableDebtToken( [ - tokenAddresses.UNI, + poolAddress, + tokenAddresses[symbol], + `Aave variable debt bearing ${symbol}`, + `variableDebt${symbol}`, + ZERO_ADDRESS, + ], + verify + ); + const rates = await deployDefaultReserveInterestRateStrategy( + [ + tokenAddresses[symbol], + optimalUtilizationRate, baseVariableBorrowRate, variableRateSlope1, variableRateSlope2, @@ -192,13 +215,13 @@ export const initReservesByHelper = async ( verify ); - deployedStableTokens.push(stableDebtUNI.address); - deployedVariableTokens.push(variableDebtUNI.address); - deployedATokens.push(aTokenUNI.address); - deployedRates.push(ratesUNI.address); - reserveInitDecimals.push(reservesParams.UNI.reserveDecimals); - reserveTokens.push(tokenAddresses.UNI); - reserveSymbols.push('UNI'); + deployedStableTokens.push(stableDebt.address); + deployedVariableTokens.push(variableDebt.address); + deployedATokens.push(aToken.address); + deployedRates.push(rates.address); + reserveInitDecimals.push(params.reserveDecimals); + reserveTokens.push(tokenAddresses[symbol]); + reserveSymbols.push(symbol); } // Deploy init reserves per chunks diff --git a/helpers/types.ts b/helpers/types.ts index 6f30622c..5467cb94 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -260,7 +260,9 @@ export enum TokenContractId { ENJ = 'ENJ', } -export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams {} +export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { + aTokenImpl: eContractid; +} export interface IReserveBorrowParams { optimalUtilizationRate: string; diff --git a/markets/aave/reservesConfigs.ts b/markets/aave/reservesConfigs.ts index e8a86c13..7b0cf988 100644 --- a/markets/aave/reservesConfigs.ts +++ b/markets/aave/reservesConfigs.ts @@ -1,6 +1,6 @@ import BigNumber from 'bignumber.js'; -import {oneRay} from '../../helpers/constants'; -import {IReserveParams} from '../../helpers/types'; +import { oneRay } from '../../helpers/constants'; +import { eContractid, IReserveParams } from '../../helpers/types'; export const strategyBase: IReserveParams = { optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(), @@ -15,6 +15,7 @@ export const strategyBase: IReserveParams = { borrowingEnabled: true, stableBorrowRateEnabled: true, reserveDecimals: '18', + aTokenImpl: eContractid.AToken, }; export const stablecoinStrategyBase: IReserveParams = { @@ -30,6 +31,7 @@ export const stablecoinStrategyBase: IReserveParams = { borrowingEnabled: true, stableBorrowRateEnabled: true, reserveDecimals: '18', + aTokenImpl: eContractid.AToken, }; export const stablecoinStrategyCentralized: IReserveParams = { @@ -45,6 +47,7 @@ export const stablecoinStrategyCentralized: IReserveParams = { borrowingEnabled: true, stableBorrowRateEnabled: true, reserveDecimals: '6', + aTokenImpl: eContractid.AToken, }; export const strategyGovernanceTokens: IReserveParams = { @@ -132,6 +135,7 @@ export const stablecoinStrategySUSD: IReserveParams = { borrowingEnabled: true, stableBorrowRateEnabled: false, reserveDecimals: '18', + aTokenImpl: eContractid.AToken, }; export const strategySNX: IReserveParams = { @@ -159,6 +163,7 @@ export const stablecoinStrategyTUSD: IReserveParams = { export const strategyUNI: IReserveParams = { ...strategyGovernanceTokens, stableBorrowRateEnabled: false, + aTokenImpl: eContractid.DelegationAwareAToken, }; export const stablecoinStrategyUSDC: IReserveParams = { @@ -190,6 +195,7 @@ export const strategyWBTC: IReserveParams = { borrowingEnabled: true, stableBorrowRateEnabled: true, reserveDecimals: '8', + aTokenImpl: eContractid.AToken, }; export const strategyWETH: IReserveParams = { @@ -205,6 +211,7 @@ export const strategyWETH: IReserveParams = { borrowingEnabled: true, stableBorrowRateEnabled: true, reserveDecimals: '18', + aTokenImpl: eContractid.AToken, }; export const strategyYFI: IReserveParams = {