diff --git a/hardhat.config.ts b/hardhat.config.ts index adf17664..1a5b2763 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -27,7 +27,7 @@ const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; // Prevent to load scripts before compilation and typechain if (!SKIP_LOAD) { - ['misc', 'migrations', 'dev', 'full', 'verifications'].forEach((folder) => { + ['misc', 'migrations', 'dev', 'full', 'verifications', 'helpers'].forEach((folder) => { const tasksPath = path.join(__dirname, 'tasks', folder); fs.readdirSync(tasksPath) .filter((pth) => pth.includes('.ts')) diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index e80d2f91..55c372a7 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -26,7 +26,7 @@ import { import { ZERO_ADDRESS } from './constants'; import { isZeroAddress } from 'ethereumjs-util'; -const chooseATokenDeployment = (id: eContractid) => { +export const chooseATokenDeployment = (id: eContractid) => { switch (id) { case eContractid.AToken: return deployGenericAToken; diff --git a/package.json b/package.json index 5d6c1dbb..7314ef39 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,9 @@ "print-config:kovan": "hardhat --network kovan print-config --pool Aave --data-provider 0xA1901785c29cBd48bfA74e46b67C736b26054fa4", "main:fork:initialize-tokens": "npm run compile && MAINNET_FORK=true hardhat full:initialize-tokens --pool Aave", "main:initialize-tokens": "npm run compile && hardhat --network main full:initialize-tokens --pool Aave", - "kovan:initialize-tokens": "npm run compile && hardhat --network kovan full:initialize-tokens --pool Aave" + "kovan:initialize-tokens": "npm run compile && hardhat --network kovan full:initialize-tokens --pool Aave", + "external:deploy-assets-kovan": "npm run compile && hardhat --network kovan external:deploy-new-asset --symbol ${SYMBOL} --verify", + "external:deploy-assets-main": "npm run compile && hardhat --network main external:deploy-new-asset --symbol ${SYMBOL} --verify" }, "devDependencies": { "@nomiclabs/buidler": "^1.4.7", diff --git a/tasks/helpers/deploy-new-asset.ts b/tasks/helpers/deploy-new-asset.ts new file mode 100644 index 00000000..912ebff1 --- /dev/null +++ b/tasks/helpers/deploy-new-asset.ts @@ -0,0 +1,101 @@ +import { task } from 'hardhat/config'; +import { EthereumNetwork } from '../../helpers/types'; +import { getTreasuryAddress } from '../../helpers/configuration'; +import * as marketConfigs from '../../markets/aave'; +import * as reserveConfigs from '../../markets/aave/reservesConfigs'; +import { chooseATokenDeployment } from '../../helpers/init-helpers'; +import { getLendingPoolAddressesProvider } from './../../helpers/contracts-getters'; +import { + deployDefaultReserveInterestRateStrategy, + deployStableDebtToken, + deployVariableDebtToken, +} from './../../helpers/contracts-deployments'; +import { setDRE } from '../../helpers/misc-utils'; +import { ZERO_ADDRESS } from './../../helpers/constants'; + +const LENDING_POOL_ADDRESS_PROVIDER = { + main: '0xb53c1a33016b2dc2ff3653530bff1848a515c8c5', + kovan: '0x652B2937Efd0B5beA1c8d54293FC1289672AFC6b', +}; + +const isSymbolValid = (symbol: string, network: EthereumNetwork) => + Object.keys(reserveConfigs).includes('strategy' + symbol) && + marketConfigs.AaveConfig.ReserveAssets[network][symbol] && + marketConfigs.AaveConfig.ReservesConfig[symbol] === reserveConfigs['strategy' + symbol]; + +task('external:deploy-new-asset', 'Deploy A token, Debt Tokens, Risk Parameters') + .addParam('symbol', `Asset symbol, needs to have configuration ready`) + .addFlag('verify', 'Verify contracts at Etherscan') + .setAction(async ({ verify, symbol }, localBRE) => { + const network = localBRE.network.name; + if (!isSymbolValid(symbol, network as EthereumNetwork)) { + throw new Error( + ` +WRONG RESERVE ASSET SETUP: + The symbol ${symbol} has no reserve Config and/or reserve Asset setup. + update /markets/aave/index.ts and add the asset address for ${network} network + update /markets/aave/reservesConfigs.ts and add parameters for ${symbol} + ` + ); + } + setDRE(localBRE); + const strategyParams = reserveConfigs['strategy' + symbol]; + const reserveAssetAddress = + marketConfigs.AaveConfig.ReserveAssets[localBRE.network.name][symbol]; + const deployCustomAToken = chooseATokenDeployment(strategyParams.aTokenImpl); + const addressProvider = await getLendingPoolAddressesProvider( + LENDING_POOL_ADDRESS_PROVIDER[network] + ); + const poolAddress = await addressProvider.getLendingPool(); + const treasuryAddress = await getTreasuryAddress(marketConfigs.AaveConfig); + const aToken = await deployCustomAToken( + [ + poolAddress, + reserveAssetAddress, + treasuryAddress, + `Aave interest bearing ${symbol}`, + `a${symbol}`, + ZERO_ADDRESS, + ], + verify + ); + const stableDebt = await deployStableDebtToken( + [ + poolAddress, + reserveAssetAddress, + `Aave stable debt bearing ${symbol}`, + `stableDebt${symbol}`, + ZERO_ADDRESS, + ], + verify + ); + const variableDebt = await deployVariableDebtToken( + [ + poolAddress, + reserveAssetAddress, + `Aave variable debt bearing ${symbol}`, + `variableDebt${symbol}`, + ZERO_ADDRESS, + ], + verify + ); + const rates = await deployDefaultReserveInterestRateStrategy( + [ + addressProvider.address, + strategyParams.optimalUtilizationRate, + strategyParams.baseVariableBorrowRate, + strategyParams.variableRateSlope1, + strategyParams.variableRateSlope2, + strategyParams.stableRateSlope1, + strategyParams.stableRateSlope2, + ], + verify + ); + console.log(` + New interest bearing asset deployed on ${network}: + Interest bearing a${symbol} address: ${aToken.address} + Variable Debt variableDebt${symbol} address: ${variableDebt.address} + Stable Debt stableDebt${symbol} address: ${stableDebt.address} + Strategy Implementation for ${symbol} address: ${rates.address} + `); + });