import { Contract } from 'ethers'; import { DRE } from './misc-utils'; import { tEthereumAddress, eContractid, tStringTokenSmallUnits, AavePools, TokenContractId, iMultiPoolsAssets, IReserveParams, PoolConfiguration, eEthereumNetwork, } from './types'; import { MintableERC20 } from '../types/MintableERC20'; import { MockContract } from 'ethereum-waffle'; import { getReservesConfigByPool } from './configuration'; import { getFirstSigner } from './contracts-getters'; import { ZERO_ADDRESS } from './constants'; import { AaveProtocolDataProviderFactory, ATokenFactory, ATokensAndRatesHelperFactory, AaveOracleFactory, DefaultReserveInterestRateStrategyFactory, DelegationAwareATokenFactory, InitializableAdminUpgradeabilityProxyFactory, LendingPoolAddressesProviderFactory, LendingPoolAddressesProviderRegistryFactory, LendingPoolCollateralManagerFactory, LendingPoolConfiguratorFactory, LendingPoolFactory, LendingRateOracleFactory, MintableDelegationERC20Factory, MintableERC20Factory, MockAggregatorFactory, MockATokenFactory, MockFlashLoanReceiverFactory, MockStableDebtTokenFactory, MockVariableDebtTokenFactory, PriceOracleFactory, ReserveLogicFactory, SelfdestructTransferFactory, StableDebtTokenFactory, VariableDebtTokenFactory, WalletBalanceProviderFactory, WETH9MockedFactory, WETHGatewayFactory, } from '../types'; import { withSaveAndVerify, registerContractInJsonDb, linkBytecode, insertContractAddressInDb, } from './contracts-helpers'; import { StableAndVariableTokensHelperFactory } from '../types/StableAndVariableTokensHelperFactory'; import { MintableDelegationERC20 } from '../types/MintableDelegationERC20'; import { readArtifact as buidlerReadArtifact } from '@nomiclabs/buidler/plugins'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { LendingPoolLibraryAddresses } from '../types/LendingPoolFactory'; const readArtifact = async (id: string) => { if (DRE.network.name === eEthereumNetwork.buidlerevm) { return buidlerReadArtifact(DRE.config.paths.artifacts, id); } return (DRE as HardhatRuntimeEnvironment).artifacts.readArtifact(id); }; export const deployUniswapLendingPoolAddressesProvider = async (marketId: string, verify?: boolean) => withSaveAndVerify( await new LendingPoolAddressesProviderFactory(await getFirstSigner()).deploy(marketId), eContractid.UniswapLendingPoolAddressesProvider, [marketId], verify ); export const deployUniswapLendingPoolConfigurator = async (verify?: boolean) => { const lendingPoolConfiguratorImpl = await new LendingPoolConfiguratorFactory( await getFirstSigner() ).deploy(); await insertContractAddressInDb( eContractid.UniswapLendingPoolConfiguratorImpl, lendingPoolConfiguratorImpl.address ); return withSaveAndVerify( lendingPoolConfiguratorImpl, eContractid.UniswapLendingPoolConfigurator, [], verify ); }; export const deployUniswapLendingPool = async (verify?: boolean) => { const libraries = await deployAaveLibraries(verify); const lendingPoolImpl = await new LendingPoolFactory(libraries, await getFirstSigner()).deploy(); await insertContractAddressInDb(eContractid.UniswapLendingPoolImpl, lendingPoolImpl.address); return withSaveAndVerify(lendingPoolImpl, eContractid.LendingPool, [], verify); }; export const deployReserveLogicLibrary = async (verify?: boolean) => withSaveAndVerify( await new ReserveLogicFactory(await getFirstSigner()).deploy(), eContractid.ReserveLogic, [], verify ); export const deployGenericLogic = async (reserveLogic: Contract, verify?: boolean) => { const genericLogicArtifact = await readArtifact(eContractid.GenericLogic); const linkedGenericLogicByteCode = linkBytecode(genericLogicArtifact, { [eContractid.ReserveLogic]: reserveLogic.address, }); const genericLogicFactory = await DRE.ethers.getContractFactory( genericLogicArtifact.abi, linkedGenericLogicByteCode ); const genericLogic = await (await genericLogicFactory.deploy()).deployed(); return withSaveAndVerify(genericLogic, eContractid.GenericLogic, [], verify); }; export const deployValidationLogic = async ( reserveLogic: Contract, genericLogic: Contract, verify?: boolean ) => { const validationLogicArtifact = await readArtifact(eContractid.ValidationLogic); const linkedValidationLogicByteCode = linkBytecode(validationLogicArtifact, { [eContractid.ReserveLogic]: reserveLogic.address, [eContractid.GenericLogic]: genericLogic.address, }); const validationLogicFactory = await DRE.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(reserveLogic, verify); const validationLogic = await deployValidationLogic(reserveLogic, genericLogic, verify); // 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. // // 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 { ['__$de8c0cf1a7d7c36c802af9a64fb9d86036$__']: validationLogic.address, ['__$22cd43a9dda9ce44e9b92ba393b88fb9ac$__']: reserveLogic.address, }; }; export const deployUniswapPriceOracle = async (verify?: boolean) => withSaveAndVerify( await new PriceOracleFactory(await getFirstSigner()).deploy(), eContractid.UniswapPriceOracle, [], verify ); export const deployUniswapLendingRateOracle = async (verify?: boolean) => withSaveAndVerify( await new LendingRateOracleFactory(await getFirstSigner()).deploy(), eContractid.UniswapLendingRateOracle, [], verify ); export const deployUniswapAaveOracle = async ( args: [tEthereumAddress[], tEthereumAddress[], tEthereumAddress, tEthereumAddress], verify?: boolean ) => withSaveAndVerify( await new AaveOracleFactory(await getFirstSigner()).deploy(...args), eContractid.UniswapAaveOracle, args, verify ); export const deployUniswapLendingPoolCollateralManager = async (verify?: boolean) => { const collateralManagerImpl = await new LendingPoolCollateralManagerFactory( await getFirstSigner() ).deploy(); await insertContractAddressInDb( eContractid.UniswapLendingPoolCollateralManagerImpl, collateralManagerImpl.address ); return withSaveAndVerify( collateralManagerImpl, eContractid.UniswapLendingPoolCollateralManager, [], verify ); }; export const deployUniswapMockFlashLoanReceiver = async ( addressesProvider: tEthereumAddress, verify?: boolean ) => withSaveAndVerify( await new MockFlashLoanReceiverFactory(await getFirstSigner()).deploy(addressesProvider), eContractid.UniswapMockFlashLoanReceiver, [addressesProvider], verify ); export const deployUniswapWalletBalancerProvider = async (verify?: boolean) => withSaveAndVerify( await new WalletBalanceProviderFactory(await getFirstSigner()).deploy(), eContractid.UniswapWalletBalanceProvider, [], verify ); export const deployUniswapWETHGateway = async ( args: [tEthereumAddress, tEthereumAddress], verify?: boolean ) => withSaveAndVerify( await new WETHGatewayFactory(await getFirstSigner()).deploy(...args), eContractid.UniswapWETHGateway, args, verify );