From aa6ab1d4eea9a0235cd73e35c40a2461269bdc67 Mon Sep 17 00:00:00 2001 From: Lasse Herskind <16536249+LHerskind@users.noreply.github.com> Date: Mon, 2 Aug 2021 11:25:21 +0200 Subject: [PATCH] feat: Add config + additional tasks + delay in `withSaveAndVerify` - Add configurations - Add tasks for minor interaction - Add a delay in `withSaveAndVerify` to handle rate limiting --- contracts/misc/ChainlinkSourcesRegistry.sol | 86 ++++++ hardhat.config.ts | 43 ++- helper-hardhat-config.ts | 2 + helpers/configuration.ts | 7 + helpers/contracts-helpers.ts | 15 +- helpers/types.ts | 28 +- markets/arbitrum/commons.ts | 128 +++++++++ markets/arbitrum/index.ts | 30 ++ markets/arbitrum/rateStrategies.ts | 105 +++++++ markets/arbitrum/reservesConfigs.ts | 266 ++++++++++++++++++ package.json | 11 +- tasks/arbitrum/borrow.ts | 43 +++ .../deploy-ChainlinkSourcesRegistry.ts | 63 +++++ tasks/arbitrum/deploy-tokens.ts | 13 + tasks/arbitrum/deposit.ts | 95 +++++++ tasks/arbitrum/lurker.ts | 121 ++++++++ .../deployments/deploy-UiPoolDataProvider.ts | 14 +- tasks/migrations/arbitrum.dev.ts | 35 +++ 18 files changed, 1087 insertions(+), 18 deletions(-) create mode 100644 contracts/misc/ChainlinkSourcesRegistry.sol create mode 100644 tasks/arbitrum/borrow.ts create mode 100644 tasks/arbitrum/deploy-ChainlinkSourcesRegistry.ts create mode 100644 tasks/arbitrum/deploy-tokens.ts create mode 100644 tasks/arbitrum/deposit.ts create mode 100644 tasks/arbitrum/lurker.ts create mode 100644 tasks/migrations/arbitrum.dev.ts diff --git a/contracts/misc/ChainlinkSourcesRegistry.sol b/contracts/misc/ChainlinkSourcesRegistry.sol new file mode 100644 index 00000000..f8127a13 --- /dev/null +++ b/contracts/misc/ChainlinkSourcesRegistry.sol @@ -0,0 +1,86 @@ +/** + *Submitted for verification at Etherscan.io on 2020-12-03 + */ + +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; + +/** + * @title VersionedInitializable + * + * @dev Helper contract to support initializer functions. To use it, replace + * the constructor with a function that has the `initializer` modifier. + * WARNING: Unlike constructors, initializer functions must be manually + * invoked. This applies both to deploying an Initializable contract, as well + * as extending an Initializable contract via inheritance. + * WARNING: When used with inheritance, manual care must be taken to not invoke + * a parent initializer twice, or ensure that all initializers are idempotent, + * because this is not dealt with automatically as with constructors. + * + * @author Aave, inspired by the OpenZeppelin Initializable contract + */ +abstract contract VersionedInitializable { + /** + * @dev Indicates that the contract has been initialized. + */ + uint256 internal lastInitializedRevision = 0; + + /** + * @dev Modifier to use in the initializer function of a contract. + */ + modifier initializer() { + uint256 revision = getRevision(); + require(revision > lastInitializedRevision, 'Contract instance has already been initialized'); + + lastInitializedRevision = revision; + + _; + } + + /// @dev returns the revision number of the contract. + /// Needs to be defined in the inherited class as a constant. + function getRevision() internal pure virtual returns (uint256); + + // Reserved storage space to allow for layout changes in the future. + uint256[50] private ______gap; +} + +contract ChainlinkSourcesRegistry is VersionedInitializable { + /// @dev Mapping of current stored asset => underlying Chainlink aggregator + mapping(address => address) public aggregatorsOfAssets; + + event AggregatorUpdated(address token, address aggregator); + + uint256 public constant REVISION = 1; + + address public manager; + + /** + * @dev returns the revision of the implementation contract + */ + function getRevision() internal pure override returns (uint256) { + return REVISION; + } + + function initialize() external initializer { + manager = msg.sender; + } + + function updateAggregators(address[] memory assets, address[] memory aggregators) external { + require(isManager(msg.sender), 'INVALID_MANAGER'); + + for (uint256 i = 0; i < assets.length; i++) { + aggregatorsOfAssets[assets[i]] = aggregators[i]; + emit AggregatorUpdated(assets[i], aggregators[i]); + } + } + + function isManager(address caller) public view returns (bool) { + return caller == manager; + } + + function setManager(address newManager) public { + require(isManager(msg.sender), 'INVALID_MANAGER'); + manager = newManager; + } +} diff --git a/hardhat.config.ts b/hardhat.config.ts index cb1b9432..a1e8779d 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -3,7 +3,13 @@ import fs from 'fs'; import { HardhatUserConfig } from 'hardhat/types'; // @ts-ignore import { accounts } from './test-wallets.js'; -import { eEthereumNetwork, eNetwork, ePolygonNetwork, eXDaiNetwork } from './helpers/types'; +import { + eArbitrumNetwork, + eEthereumNetwork, + eNetwork, + ePolygonNetwork, + eXDaiNetwork, +} from './helpers/types'; import { BUIDLEREVM_CHAINID, COVERAGE_CHAINID } from './helpers/buidler-constants'; import { NETWORKS_RPC_URL, @@ -34,16 +40,23 @@ const UNLIMITED_BYTECODE_SIZE = process.env.UNLIMITED_BYTECODE_SIZE === 'true'; // Prevent to load scripts before compilation and typechain if (!SKIP_LOAD) { - ['misc', 'migrations', 'dev', 'full', 'verifications', 'deployments', 'helpers'].forEach( - (folder) => { - const tasksPath = path.join(__dirname, 'tasks', folder); - fs.readdirSync(tasksPath) - .filter((pth) => pth.includes('.ts')) - .forEach((task) => { - require(`${tasksPath}/${task}`); - }); - } - ); + [ + 'misc', + 'migrations', + 'dev', + 'full', + 'verifications', + 'deployments', + 'helpers', + 'arbitrum', + ].forEach((folder) => { + const tasksPath = path.join(__dirname, 'tasks', folder); + fs.readdirSync(tasksPath) + .filter((pth) => pth.includes('.ts')) + .forEach((task) => { + require(`${tasksPath}/${task}`); + }); + }); } require(`${path.join(__dirname, 'tasks/misc')}/set-bre.ts`); @@ -115,6 +128,14 @@ const buidlerConfig: HardhatUserConfig = { })), forking: buildForkConfig(), }, + arbitrum_rinkeby: { + gasPrice: 0, + url: NETWORKS_RPC_URL[eArbitrumNetwork.rinkeby], + accounts: accounts.map( + ({ secretKey, balance }: { secretKey: string; balance: string }) => secretKey + ), + chainId: 421611, + }, buidlerevm_docker: { hardfork: 'berlin', blockGasLimit: 9500000, diff --git a/helper-hardhat-config.ts b/helper-hardhat-config.ts index 2cfe077b..9260a023 100644 --- a/helper-hardhat-config.ts +++ b/helper-hardhat-config.ts @@ -1,6 +1,7 @@ // @ts-ignore import { HardhatNetworkForkingUserConfig, HardhatUserConfig } from 'hardhat/types'; import { + eArbitrumNetwork, eEthereumNetwork, ePolygonNetwork, eXDaiNetwork, @@ -49,6 +50,7 @@ export const NETWORKS_RPC_URL: iParamsPerNetwork = { [ePolygonNetwork.mumbai]: 'https://rpc-mumbai.maticvigil.com', [ePolygonNetwork.matic]: 'https://rpc-mainnet.matic.network', [eXDaiNetwork.xdai]: 'https://rpc.xdaichain.com/', + [eArbitrumNetwork.rinkeby]: `https://arb-rinkeby.g.alchemy.com/v2/${ALCHEMY_KEY}`, }; export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { diff --git a/helpers/configuration.ts b/helpers/configuration.ts index 5e682ee7..3fc72dcf 100644 --- a/helpers/configuration.ts +++ b/helpers/configuration.ts @@ -10,6 +10,7 @@ import { getEthersSignersAddresses, getParamPerPool } from './contracts-helpers' import AaveConfig from '../markets/aave'; import MaticConfig from '../markets/matic'; import AmmConfig from '../markets/amm'; +import ArbitrumConfig from '../markets/arbitrum'; import { CommonsConfig } from '../markets/aave/commons'; import { DRE, filterMapBy } from './misc-utils'; @@ -22,6 +23,7 @@ export enum ConfigNames { Aave = 'Aave', Matic = 'Matic', Amm = 'Amm', + Arbitrum = 'Arbitrum', } export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => { @@ -34,6 +36,8 @@ export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => { return AmmConfig; case ConfigNames.Commons: return CommonsConfig; + case ConfigNames.Arbitrum: + return ArbitrumConfig; default: throw new Error( `Unsupported pool configuration: ${configName} is not one of the supported configs ${Object.values( @@ -59,6 +63,9 @@ export const getReservesConfigByPool = (pool: AavePools): iMultiPoolsAssets( args: (string | string[])[], verify?: boolean ): Promise => { + const delay = (ms: number) => new Promise((res) => setTimeout(res, ms)); + await delay(2500); await waitForTx(instance.deployTransaction); await registerContractInJsonDb(id, instance); if (verify) { @@ -147,6 +152,7 @@ export const getParamPerNetwork = (param: iParamsPerNetwork, network: eNet param as iEthereumParamsPerNetwork; const { matic, mumbai } = param as iPolygonParamsPerNetwork; const { xdai } = param as iXDaiParamsPerNetwork; + const { arbitrum_rinkeby } = param as iArbitrumParamsPerNetwork; if (process.env.FORK) { return param[process.env.FORK as eNetwork] as T; } @@ -172,6 +178,8 @@ export const getParamPerNetwork = (param: iParamsPerNetwork, network: eNet return mumbai; case eXDaiNetwork.xdai: return xdai; + case eArbitrumNetwork.rinkeby: + return arbitrum_rinkeby; } }; @@ -185,7 +193,10 @@ export const getOptionalParamAddressPerNetwork = ( return getParamPerNetwork(param, network); }; -export const getParamPerPool = ({ proto, amm, matic }: iParamsPerPool, pool: AavePools) => { +export const getParamPerPool = ( + { proto, amm, matic, arbitrum }: iParamsPerPool, + pool: AavePools +) => { switch (pool) { case AavePools.proto: return proto; @@ -193,6 +204,8 @@ export const getParamPerPool = ({ proto, amm, matic }: iParamsPerPool, poo return amm; case AavePools.matic: return matic; + case AavePools.arbitrum: + return arbitrum; default: return proto; } diff --git a/helpers/types.ts b/helpers/types.ts index a533a040..cbc38d3c 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -4,7 +4,7 @@ export interface SymbolMap { [symbol: string]: T; } -export type eNetwork = eEthereumNetwork | ePolygonNetwork | eXDaiNetwork; +export type eNetwork = eEthereumNetwork | ePolygonNetwork | eXDaiNetwork | eArbitrumNetwork; export enum eEthereumNetwork { buidlerevm = 'buidlerevm', @@ -16,6 +16,10 @@ export enum eEthereumNetwork { tenderly = 'tenderly', } +export enum eArbitrumNetwork { + rinkeby = 'arbitrum_rinkeby', +} + export enum ePolygonNetwork { matic = 'matic', mumbai = 'mumbai', @@ -38,6 +42,7 @@ export enum AavePools { proto = 'proto', matic = 'matic', amm = 'amm', + arbitrum = 'arbitrum', } export enum eContractid { @@ -198,6 +203,7 @@ export type tBigNumberTokenSmallUnits = BigNumber; export interface iAssetCommon { [key: string]: T; } + export interface iAssetBase { WETH: T; DAI: T; @@ -270,6 +276,11 @@ export type iAavePoolAssets = Pick< | 'xSUSHI' >; +export type iArbitrumAavePoolAssets = Pick< + iAssetsWithoutUSD, + 'USDT' | 'LINK' | 'WBTC' | 'WETH' +>; + export type iLpPoolAssets = Pick< iAssetsWithoutUSD, | 'DAI' @@ -394,12 +405,14 @@ export interface IMarketRates { export type iParamsPerNetwork = | iEthereumParamsPerNetwork | iPolygonParamsPerNetwork - | iXDaiParamsPerNetwork; + | iXDaiParamsPerNetwork + | iArbitrumParamsPerNetwork; export interface iParamsPerNetworkAll extends iEthereumParamsPerNetwork, iPolygonParamsPerNetwork, - iXDaiParamsPerNetwork {} + iXDaiParamsPerNetwork, + iArbitrumParamsPerNetwork {} export interface iEthereumParamsPerNetwork { [eEthereumNetwork.coverage]: T; @@ -411,6 +424,10 @@ export interface iEthereumParamsPerNetwork { [eEthereumNetwork.tenderly]: T; } +export interface iArbitrumParamsPerNetwork { + [eArbitrumNetwork.rinkeby]: T; +} + export interface iPolygonParamsPerNetwork { [ePolygonNetwork.matic]: T; [ePolygonNetwork.mumbai]: T; @@ -424,6 +441,7 @@ export interface iParamsPerPool { [AavePools.proto]: T; [AavePools.matic]: T; [AavePools.amm]: T; + [AavePools.arbitrum]: T; } export interface iBasicDistributionParams { @@ -507,6 +525,10 @@ export interface IAaveConfiguration extends ICommonConfiguration { ReservesConfig: iAavePoolAssets; } +export interface IArbitrumConfiguration extends ICommonConfiguration { + ReservesConfig: iArbitrumAavePoolAssets; +} + export interface IAmmConfiguration extends ICommonConfiguration { ReservesConfig: iLpPoolAssets; } diff --git a/markets/arbitrum/commons.ts b/markets/arbitrum/commons.ts index e69de29b..b5e689f0 100644 --- a/markets/arbitrum/commons.ts +++ b/markets/arbitrum/commons.ts @@ -0,0 +1,128 @@ +import { zeroAddress } from 'ethereumjs-util/dist'; +import { + oneRay, + ZERO_ADDRESS, + MOCK_CHAINLINK_AGGREGATORS_PRICES, + oneEther, + oneUsd, +} from '../../helpers/constants'; +import { ICommonConfiguration, eArbitrumNetwork } from '../../helpers/types'; + +// ---------------- +// PROTOCOL GLOBAL PARAMS +// ---------------- + +export const CommonsConfig: ICommonConfiguration = { + MarketId: 'Arbitrum', + ATokenNamePrefix: 'Arbitrum Aave interest bearing', + StableDebtTokenNamePrefix: 'Aave stable debt bearing', + VariableDebtTokenNamePrefix: 'Aave variable debt bearing', + SymbolPrefix: '', + ProviderId: 0, // Overriden in index.ts + OracleQuoteCurrency: 'USD', + OracleQuoteUnit: oneUsd.toString(), + ProtocolGlobalParams: { + TokenDistributorPercentageBase: '10000', + MockUsdPriceInWei: '5848466240000000', + UsdAddress: '0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96', + NilAddress: '0x0000000000000000000000000000000000000000', + OneAddress: '0x0000000000000000000000000000000000000001', + AaveReferral: '0', + }, + + // ---------------- + // COMMON PROTOCOL PARAMS ACROSS POOLS AND NETWORKS + // ---------------- + + Mocks: { + AllAssetsInitialPrices: { + ...MOCK_CHAINLINK_AGGREGATORS_PRICES, + }, + }, + // TODO: reorg alphabetically, checking the reason of tests failing + LendingRateOracleRatesCommon: { + WETH: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + USDT: { + borrowRate: oneRay.multipliedBy(0.035).toFixed(), + }, + LINK: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + WBTC: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, + }, + // ---------------- + // COMMON PROTOCOL ADDRESSES ACROSS POOLS + // ---------------- + + // If PoolAdmin/emergencyAdmin is set, will take priority over PoolAdminIndex/emergencyAdminIndex + PoolAdmin: { + [eArbitrumNetwork.rinkeby]: undefined, + }, + PoolAdminIndex: 0, + EmergencyAdmin: { + [eArbitrumNetwork.rinkeby]: undefined, + }, + EmergencyAdminIndex: 1, + ProviderRegistry: { + [eArbitrumNetwork.rinkeby]: '', + }, + ProviderRegistryOwner: { + [eArbitrumNetwork.rinkeby]: '', + }, + LendingRateOracle: { + [eArbitrumNetwork.rinkeby]: '', + }, + LendingPoolCollateralManager: { + [eArbitrumNetwork.rinkeby]: '', + }, + LendingPoolConfigurator: { + [eArbitrumNetwork.rinkeby]: '', + }, + LendingPool: { + [eArbitrumNetwork.rinkeby]: '', + }, + WethGateway: { + [eArbitrumNetwork.rinkeby]: '', + }, + TokenDistributor: { + [eArbitrumNetwork.rinkeby]: '', + }, + AaveOracle: { + [eArbitrumNetwork.rinkeby]: ZERO_ADDRESS, + }, + FallbackOracle: { + [eArbitrumNetwork.rinkeby]: ZERO_ADDRESS, + }, + ChainlinkAggregator: { + [eArbitrumNetwork.rinkeby]: { + WETH: '0x5f0423B1a6935dc5596e7A24d98532b67A0AeFd8', + USD: '0x5f0423B1a6935dc5596e7A24d98532b67A0AeFd8', + LINK: '0x52C9Eb2Cc68555357221CAe1e5f2dD956bC194E5', + WBTC: '0x0c9973e7a27d00e656B9f153348dA46CaD70d03d', + USDT: '0xb1Ac85E779d05C2901812d812210F6dE144b2df0', + }, + }, + ReserveAssets: { + [eArbitrumNetwork.rinkeby]: {}, + }, + ReservesConfig: {}, + ATokenDomainSeparator: { + [eArbitrumNetwork.rinkeby]: '', + }, + WETH: { + [eArbitrumNetwork.rinkeby]: '0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681', + }, + WrappedNativeToken: { + [eArbitrumNetwork.rinkeby]: '0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681', + }, + ReserveFactorTreasuryAddress: { + [eArbitrumNetwork.rinkeby]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', + }, + IncentivesController: { + [eArbitrumNetwork.rinkeby]: ZERO_ADDRESS, + }, +}; diff --git a/markets/arbitrum/index.ts b/markets/arbitrum/index.ts index 8b137891..2dbf1461 100644 --- a/markets/arbitrum/index.ts +++ b/markets/arbitrum/index.ts @@ -1 +1,31 @@ +import { oneRay, ZERO_ADDRESS } from '../../helpers/constants'; +import { eArbitrumNetwork, eEthereumNetwork, IArbitrumConfiguration } from '../../helpers/types'; +import { CommonsConfig } from './commons'; +import { strategyUSDT, strategyLINK, strategyWBTC, strategyWETH } from './reservesConfigs'; + +// ---------------- +// POOL--SPECIFIC PARAMS +// ---------------- + +export const ArbitrumConfig: IArbitrumConfiguration = { + ...CommonsConfig, + MarketId: 'Aave arbitrum market', + ProviderId: 1, + ReservesConfig: { + LINK: strategyLINK, + USDT: strategyUSDT, + WBTC: strategyWBTC, + WETH: strategyWETH, + }, + ReserveAssets: { + [eArbitrumNetwork.rinkeby]: { + WETH: '0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681', + WBTC: '0x80205a8848fb7B8f7CCc4fb029662C34f190bF58', + USDT: '0xfa641839FCC50db7420afE9f385CA1dfdF4ac744', + LINK: '0xC3188739EdC9b53a61Cf0c24A31B9A76aCAFf5Ca', + }, + }, +}; + +export default ArbitrumConfig; diff --git a/markets/arbitrum/rateStrategies.ts b/markets/arbitrum/rateStrategies.ts index e69de29b..4a7125dd 100644 --- a/markets/arbitrum/rateStrategies.ts +++ b/markets/arbitrum/rateStrategies.ts @@ -0,0 +1,105 @@ +import BigNumber from 'bignumber.js'; +import { oneRay } from '../../helpers/constants'; +import { IInterestRateStrategyParams } from '../../helpers/types'; + +// BUSD SUSD +export const rateStrategyStableOne: IInterestRateStrategyParams = { + name: "rateStrategyStableOne", + optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(), + stableRateSlope1: '0', + stableRateSlope2: '0', +}; + +// DAI TUSD +export const rateStrategyStableTwo: IInterestRateStrategyParams = { + name: "rateStrategyStableTwo", + optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(), + stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(), + stableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(), +} + +// USDC USDT +export const rateStrategyStableThree: IInterestRateStrategyParams = { + name: "rateStrategyStableThree", + optimalUtilizationRate: new BigNumber(0.9).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(), + stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(), + stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(), +} + +// WETH +export const rateStrategyWETH: IInterestRateStrategyParams = { + name: "rateStrategyWETH", + optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(), + stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(), + stableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(), +} + +// AAVE +export const rateStrategyAAVE: IInterestRateStrategyParams = { + name: "rateStrategyAAVE", + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: '0', + variableRateSlope2: '0', + stableRateSlope1: '0', + stableRateSlope2: '0', +} + +// BAT ENJ LINK MANA MKR REN YFI ZRX +export const rateStrategyVolatileOne: IInterestRateStrategyParams = { + name: "rateStrategyVolatileOne", + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(), + stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(), + stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(), +} + +// KNC WBTC +export const rateStrategyVolatileTwo: IInterestRateStrategyParams = { + name: "rateStrategyVolatileTwo", + optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(), + stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(), + stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(), +} + +// SNX +export const rateStrategyVolatileThree: IInterestRateStrategyParams = { + name: "rateStrategyVolatileThree", + optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(), + variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(), + stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(), + stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(), +} + + +export const rateStrategyVolatileFour: IInterestRateStrategyParams = { + name: "rateStrategyVolatileFour", + optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(), + baseVariableBorrowRate: '0', + variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(), + variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(), + stableRateSlope1: '0', + stableRateSlope2: '0', +} + + + diff --git a/markets/arbitrum/reservesConfigs.ts b/markets/arbitrum/reservesConfigs.ts index e69de29b..b41ae417 100644 --- a/markets/arbitrum/reservesConfigs.ts +++ b/markets/arbitrum/reservesConfigs.ts @@ -0,0 +1,266 @@ +import { eContractid, IReserveParams } from '../../helpers/types'; + +import { + rateStrategyStableOne, + rateStrategyStableTwo, + rateStrategyStableThree, + rateStrategyWETH, + rateStrategyAAVE, + rateStrategyVolatileOne, + rateStrategyVolatileTwo, + rateStrategyVolatileThree, + rateStrategyVolatileFour, +} from './rateStrategies'; + +export const strategyBUSD: IReserveParams = { + strategy: rateStrategyStableOne, + baseLTVAsCollateral: '0', + liquidationThreshold: '0', + liquidationBonus: '0', + borrowingEnabled: true, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000', +}; + +export const strategyDAI: IReserveParams = { + strategy: rateStrategyStableTwo, + baseLTVAsCollateral: '7500', + liquidationThreshold: '8000', + liquidationBonus: '10500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000', +}; + +export const strategySUSD: IReserveParams = { + strategy: rateStrategyStableOne, + baseLTVAsCollateral: '0', + liquidationThreshold: '0', + liquidationBonus: '0', + borrowingEnabled: true, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '2000', +}; + +export const strategyTUSD: IReserveParams = { + strategy: rateStrategyStableTwo, + baseLTVAsCollateral: '7500', + liquidationThreshold: '8000', + liquidationBonus: '10500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000', +}; + +export const strategyUSDC: IReserveParams = { + strategy: rateStrategyStableThree, + baseLTVAsCollateral: '8000', + liquidationThreshold: '8500', + liquidationBonus: '10500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '6', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000', +}; + +export const strategyUSDT: IReserveParams = { + strategy: rateStrategyStableThree, + baseLTVAsCollateral: '8000', + liquidationThreshold: '8500', + liquidationBonus: '10500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '6', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000', +}; + +export const strategyAAVE: IReserveParams = { + strategy: rateStrategyAAVE, + baseLTVAsCollateral: '5000', + liquidationThreshold: '6500', + liquidationBonus: '11000', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '0', +}; + +export const strategyBAT: IReserveParams = { + strategy: rateStrategyVolatileOne, + baseLTVAsCollateral: '7000', + liquidationThreshold: '7500', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '2000', +}; + +export const strategyENJ: IReserveParams = { + strategy: rateStrategyVolatileOne, + baseLTVAsCollateral: '5500', + liquidationThreshold: '6000', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '2000', +}; + +export const strategyWETH: IReserveParams = { + strategy: rateStrategyWETH, + baseLTVAsCollateral: '8000', + liquidationThreshold: '8250', + liquidationBonus: '10500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000', +}; + +export const strategyKNC: IReserveParams = { + strategy: rateStrategyVolatileTwo, + baseLTVAsCollateral: '6000', + liquidationThreshold: '6500', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '2000', +}; + +export const strategyLINK: IReserveParams = { + strategy: rateStrategyVolatileOne, + baseLTVAsCollateral: '7000', + liquidationThreshold: '7500', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '2000', +}; + +export const strategyMANA: IReserveParams = { + strategy: rateStrategyVolatileOne, + baseLTVAsCollateral: '6000', + liquidationThreshold: '6500', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '3500', +}; + +export const strategyMKR: IReserveParams = { + strategy: rateStrategyVolatileOne, + baseLTVAsCollateral: '6000', + liquidationThreshold: '6500', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '2000', +}; + +export const strategyREN: IReserveParams = { + strategy: rateStrategyVolatileOne, + baseLTVAsCollateral: '5500', + liquidationThreshold: '6000', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '2000', +}; + +export const strategySNX: IReserveParams = { + strategy: rateStrategyVolatileThree, + baseLTVAsCollateral: '1500', + liquidationThreshold: '4000', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '3500', +}; + +// Invalid borrow rates in params currently, replaced with snx params +export const strategyUNI: IReserveParams = { + strategy: rateStrategyVolatileThree, + baseLTVAsCollateral: '6000', + liquidationThreshold: '6500', + liquidationBonus: '11000', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.DelegationAwareAToken, + reserveFactor: '2000', +}; + +export const strategyWBTC: IReserveParams = { + strategy: rateStrategyVolatileTwo, + baseLTVAsCollateral: '7000', + liquidationThreshold: '7500', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '8', + aTokenImpl: eContractid.AToken, + reserveFactor: '2000', +}; + +export const strategyYFI: IReserveParams = { + strategy: rateStrategyVolatileOne, + baseLTVAsCollateral: '4000', + liquidationThreshold: '5500', + liquidationBonus: '11500', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '2000', +}; + +export const strategyZRX: IReserveParams = { + strategy: rateStrategyVolatileOne, + baseLTVAsCollateral: '6000', + liquidationThreshold: '6500', + liquidationBonus: '11000', + borrowingEnabled: true, + stableBorrowRateEnabled: true, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '2000', +}; + +export const strategyXSUSHI: IReserveParams = { + strategy: rateStrategyVolatileFour, + baseLTVAsCollateral: '2500', + liquidationThreshold: '4500', + liquidationBonus: '11500', + borrowingEnabled: true, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + reserveFactor: '3500', +}; diff --git a/package.json b/package.json index b9debafc..344f6330 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,14 @@ "artifacts" ], "scripts": { + "hardhat:arbitrum:dev": "hardhat --network arbitrum_rinkeby", + "arbitrum:dev:full:migration": "npm run compile && npm run hardhat:arbitrum:dev -- arbitrum:dev", + "arbitrum:dev:lurker": "npm run hardhat:arbitrum:dev -- arbitrum:lurker", + "arbitrum:dev:deploy-mocks": "npm run hardhat:arbitrum:dev -- arbitrum:deploy-mock-tokens", + "arbitrum:dev:deposit:wbtc": "npm run hardhat:arbitrum:dev -- arbitrum:deposit:wbtc", + "arbitrum:dev:deposit:eth": "npm run hardhat:arbitrum:dev -- arbitrum:deposit:eth", + "arbitrum:dev:borrow:wbtc": "npm run hardhat:arbitrum:dev -- arbitrum:borrow:wbtc", + "arbitrum:dev:deploy:chainlink-reg": "npm run hardhat:arbitrum:dev -- arbitrum:deploy:chainlink-sources-registry", "run-env": "npm i && tail -f /dev/null", "hardhat": "hardhat", "hardhat:kovan": "hardhat --network kovan", @@ -150,7 +158,8 @@ "Andrey Kozlov ", "David Racero ", "Pol Sendra ", - "David Truong " + "David Truong ", + "Lasse Herskind " ], "license": "AGPLv3", "dependencies": { diff --git a/tasks/arbitrum/borrow.ts b/tasks/arbitrum/borrow.ts new file mode 100644 index 00000000..f08afa2f --- /dev/null +++ b/tasks/arbitrum/borrow.ts @@ -0,0 +1,43 @@ +import { getArtifactFromContractOutput } from '@nomiclabs/buidler/internal/artifacts'; +import { formatEther, formatUnits, parseUnits } from 'ethers/lib/utils'; +import { task } from 'hardhat/config'; +import { ConfigNames, loadPoolConfig } from '../../helpers/configuration'; +import { deployAllMockTokens } from '../../helpers/contracts-deployments'; +import { + getAToken, + getFirstSigner, + getIErc20Detailed, + getLendingPool, + getMockedTokens, + getStableDebtToken, + getVariableDebtToken, +} from '../../helpers/contracts-getters'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { eEthereumNetwork } from '../../helpers/types'; +import { LendingPool } from '../../types'; + +task('arbitrum:borrow:wbtc', 'Borrow WBTC from the arbtirum market').setAction( + async ({}, localBRE) => { + await localBRE.run('set-DRE'); + + const signer = await getFirstSigner(); + const signerAddress = await signer.getAddress(); + const ethBalance = await signer.getBalance(); + + console.log(`Using: ${signerAddress} with ${formatEther(ethBalance)} eth`); + + const lendingPool = await getLendingPool(); + + // Need to look up the wbtc balance and such + const config = loadPoolConfig(ConfigNames.Arbitrum); + const tokens = await getMockedTokens(config); + + // WBTC + const wbtc = tokens['WBTC']; + const borrowAmount = parseUnits('2.5', 8); + const borrowTx = await lendingPool + .connect(signer) + .borrow(wbtc.address, borrowAmount, 2, 0, signerAddress); + console.log(`Borrow tx: ${borrowTx.hash}`); + } +); diff --git a/tasks/arbitrum/deploy-ChainlinkSourcesRegistry.ts b/tasks/arbitrum/deploy-ChainlinkSourcesRegistry.ts new file mode 100644 index 00000000..fc840722 --- /dev/null +++ b/tasks/arbitrum/deploy-ChainlinkSourcesRegistry.ts @@ -0,0 +1,63 @@ +import { getArtifactFromContractOutput } from '@nomiclabs/buidler/internal/artifacts'; +import { sign } from 'crypto'; +import { formatEther, formatUnits, parseUnits } from 'ethers/lib/utils'; +import { task } from 'hardhat/config'; +import { ConfigNames, loadPoolConfig } from '../../helpers/configuration'; +import { deployAllMockTokens } from '../../helpers/contracts-deployments'; +import { + getAToken, + getFirstSigner, + getIErc20Detailed, + getLendingPool, + getMockedTokens, + getStableDebtToken, + getVariableDebtToken, +} from '../../helpers/contracts-getters'; +import { getParamPerNetwork, withSaveAndVerify } from '../../helpers/contracts-helpers'; +import { eArbitrumNetwork, eContractid, eEthereumNetwork } from '../../helpers/types'; +import { ChainlinkSourcesRegistryFactory, LendingPool } from '../../types'; + +const deployChainlinkSourcesRegistry = async (verify: boolean) => { + return withSaveAndVerify( + await new ChainlinkSourcesRegistryFactory(await getFirstSigner()).deploy(), + 'ChainlinkSourcesRegistry', + [], + verify + ); +}; + +task( + 'arbitrum:deploy:chainlink-sources-registry', + 'Deploy chainlink sources registry to arbitrum' +).setAction(async ({}, localBRE) => { + await localBRE.run('set-DRE'); + + const conf = loadPoolConfig(ConfigNames.Arbitrum); + const network = localBRE.network.name; + + let assetNames = Object.keys(conf.ReserveAssets[network]); + let assets: string[] = []; + let aggregators: string[] = []; + + assetNames.forEach((assetName) => { + assets.push(conf.ReserveAssets[network][assetName]); + aggregators.push(conf.ChainlinkAggregator[network][assetName]); + }); + + console.log('Assets', assets, 'Aggregators', aggregators); + + const signer = await getFirstSigner(); + + const chainlinkSourcesRegistry = await deployChainlinkSourcesRegistry(false); + console.log(`Deployed ChainlinkSourcesRegistry to: ${chainlinkSourcesRegistry.address}`); + + await chainlinkSourcesRegistry.connect(signer).initialize(); + await chainlinkSourcesRegistry.connect(signer).updateAggregators(assets, aggregators); + + // Lookup to see if it updated + for (let i = 0; i < assets.length; i++) { + let asset = assets[i]; + const aggregatorFromContract = await chainlinkSourcesRegistry.aggregatorsOfAssets(asset); + console.log(`${assetNames[i]} at ${asset} with aggregator at: ${aggregatorFromContract}`); + } +}); diff --git a/tasks/arbitrum/deploy-tokens.ts b/tasks/arbitrum/deploy-tokens.ts new file mode 100644 index 00000000..ee5ef287 --- /dev/null +++ b/tasks/arbitrum/deploy-tokens.ts @@ -0,0 +1,13 @@ +import { task } from 'hardhat/config'; +import { ConfigNames, loadPoolConfig } from '../../helpers/configuration'; +import { deployAllMockTokens, deployMockTokens } from '../../helpers/contracts-deployments'; +import { getFirstSigner, getMockedTokens } from '../../helpers/contracts-getters'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { eEthereumNetwork } from '../../helpers/types'; + +task('arbitrum:deploy-mock-tokens', 'Deploy mock tokens').setAction(async ({}, localBRE) => { + await localBRE.run('set-DRE'); + const conf = loadPoolConfig(ConfigNames.Arbitrum); + + await deployMockTokens(conf, false); +}); diff --git a/tasks/arbitrum/deposit.ts b/tasks/arbitrum/deposit.ts new file mode 100644 index 00000000..c4192e16 --- /dev/null +++ b/tasks/arbitrum/deposit.ts @@ -0,0 +1,95 @@ +import { getArtifactFromContractOutput } from '@nomiclabs/buidler/internal/artifacts'; +import { formatEther, formatUnits, parseUnits } from 'ethers/lib/utils'; +import { task } from 'hardhat/config'; +import { ConfigNames, loadPoolConfig } from '../../helpers/configuration'; +import { deployAllMockTokens } from '../../helpers/contracts-deployments'; +import { + getAToken, + getFirstSigner, + getIErc20Detailed, + getLendingPool, + getMockedTokens, + getStableDebtToken, + getVariableDebtToken, + getWETHGateway, +} from '../../helpers/contracts-getters'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { eEthereumNetwork } from '../../helpers/types'; +import { LendingPool } from '../../types'; + +task('arbitrum:deposit:usdt', 'Deposit usdt into the arbitrum market').setAction( + async ({}, localBRE) => { + await localBRE.run('set-DRE'); + + const signer = await getFirstSigner(); + const signerAddress = await signer.getAddress(); + const ethBalance = await signer.getBalance(); + + console.log(`Using: ${signerAddress} with ${formatEther(ethBalance)} eth`); + + const lendingPool = await getLendingPool(); + + // Need to look up the USDT balance and such + const config = loadPoolConfig(ConfigNames.Arbitrum); + const tokens = await getMockedTokens(config); + + // USDT + const usdt = tokens['USDT']; + const depositAmount = parseUnits('1', 6); + await usdt.connect(signer).mint(depositAmount); + await usdt.connect(signer).approve(lendingPool.address, depositAmount); + const depositTx = await lendingPool + .connect(signer) + .deposit(usdt.address, depositAmount, signerAddress, 0); + console.log(`Deposit tx: ${depositTx.hash}`); + } +); + +task('arbitrum:deposit:wbtc', 'Deposit WBTC into the arbitrum market').setAction( + async ({}, localBRE) => { + await localBRE.run('set-DRE'); + + const signer = await getFirstSigner(); + const signerAddress = await signer.getAddress(); + const ethBalance = await signer.getBalance(); + + console.log(`Using: ${signerAddress} with ${formatEther(ethBalance)} eth`); + + const lendingPool = await getLendingPool(); + + // Need to look up the wbtc balance and such + const config = loadPoolConfig(ConfigNames.Arbitrum); + const tokens = await getMockedTokens(config); + + // WBTC + const wbtc = tokens['WBTC']; + const depositAmount = parseUnits('5', 8); + await wbtc.connect(signer).mint(depositAmount); + await wbtc.connect(signer).approve(lendingPool.address, depositAmount); + const depositTx = await lendingPool + .connect(signer) + .deposit(wbtc.address, depositAmount, signerAddress, 0); + console.log(`Deposit tx: ${depositTx.hash}`); + } +); + +task('arbitrum:deposit:eth', 'Deposit eth into the arbitrum market').setAction( + async ({}, localBRE) => { + await localBRE.run('set-DRE'); + + const signer = await getFirstSigner(); + const signerAddress = await signer.getAddress(); + const ethBalance = await signer.getBalance(); + + console.log(`Using: ${signerAddress} with ${formatEther(ethBalance)} eth`); + + const lendingPool = await getLendingPool(); + + const gateway = await getWETHGateway(); + const depositAmount = parseUnits('0.1', 18); + const depositTx = await gateway + .connect(signer) + .depositETH(lendingPool.address, signerAddress, 0, { value: depositAmount }); + console.log(`Deposit tx: ${depositTx.hash}`); + } +); diff --git a/tasks/arbitrum/lurker.ts b/tasks/arbitrum/lurker.ts new file mode 100644 index 00000000..c376e7de --- /dev/null +++ b/tasks/arbitrum/lurker.ts @@ -0,0 +1,121 @@ +import { getArtifactFromContractOutput } from '@nomiclabs/buidler/internal/artifacts'; +import { formatEther, formatUnits } from 'ethers/lib/utils'; +import { task } from 'hardhat/config'; +import { ConfigNames, loadPoolConfig } from '../../helpers/configuration'; +import { deployAllMockTokens } from '../../helpers/contracts-deployments'; +import { + getAToken, + getFirstSigner, + getIErc20Detailed, + getLendingPool, + getMockedTokens, + getStableDebtToken, + getVariableDebtToken, +} from '../../helpers/contracts-getters'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { eEthereumNetwork } from '../../helpers/types'; +import { LendingPool } from '../../types'; + +task('arbitrum:lurker', 'Deploy mock tokens for dev enviroment').setAction(async ({}, localBRE) => { + await localBRE.run('set-DRE'); + + const signer = await getFirstSigner(); + const signerAddress = await signer.getAddress(); + const ethBalance = await signer.getBalance(); + + console.log(`Using: ${signerAddress} with ${formatEther(ethBalance)} eth`); + + const lendingPool = await getLendingPool(); + + // Need to look up the wbtc balance and such + const config = loadPoolConfig(ConfigNames.Arbitrum); + const tokens = await getMockedTokens(config); + + // WBTC + const wbtc = tokens['WBTC']; + const wbtcReserveData = await lendingPool.getReserveData(wbtc.address); + const stableDebtWBTC = await getStableDebtToken(wbtcReserveData.stableDebtTokenAddress); + const variableDebtWBTC = await getVariableDebtToken(wbtcReserveData.variableDebtTokenAddress); + const awbtc = await getAToken(wbtcReserveData.aTokenAddress); + + const wbtcBalance = await wbtc.balanceOf(signerAddress); + const wbtcStableDebt = await stableDebtWBTC.balanceOf(signerAddress); + const wbtcVariableDebt = await variableDebtWBTC.balanceOf(signerAddress); + const wbtcTotalDebt = wbtcStableDebt.add(wbtcVariableDebt); + const awbtcBalance = await awbtc.balanceOf(signerAddress); + + console.log( + `WBTC balance: ${formatUnits(wbtcBalance, 8)}, aWBTC balance: ${formatUnits(awbtcBalance, 8)}.` + ); + console.log( + `WBTC stable debt: ${formatUnits(wbtcStableDebt, 8)}, WBTC variable debt: ${formatUnits( + wbtcVariableDebt, + 8 + )}` + ); + + // USDT + const usdt = tokens['USDT']; + const usdtReserveData = await lendingPool.getReserveData(usdt.address); + const stableDebtUSDT = await getStableDebtToken(usdtReserveData.stableDebtTokenAddress); + const variableDebtUSDT = await getVariableDebtToken(usdtReserveData.variableDebtTokenAddress); + const ausdt = await getAToken(usdtReserveData.aTokenAddress); + + const usdtBalance = await usdt.balanceOf(signerAddress); + const usdtStableDebt = await stableDebtUSDT.balanceOf(signerAddress); + const usdtVariableDebt = await variableDebtUSDT.balanceOf(signerAddress); + const usdtTotalDebt = usdtStableDebt.add(usdtVariableDebt); + const ausdtBalance = await ausdt.balanceOf(signerAddress); + + console.log( + `USDT balance: ${formatUnits(usdtBalance, 6)}, aUSDT balance: ${formatUnits(ausdtBalance, 6)}.` + ); + console.log( + `USDT stable debt: ${formatUnits(usdtStableDebt, 6)}, USDT variable debt: ${formatUnits( + usdtVariableDebt, + 6 + )}` + ); + + // WETH + const weth = await getIErc20Detailed('0xB47e6A5f8b33b3F17603C83a0535A9dcD7E32681'); + const wethReserveData = await lendingPool.getReserveData(weth.address); + const stableDebtWeth = await getStableDebtToken(wethReserveData.stableDebtTokenAddress); + const variableDebtWeth = await getVariableDebtToken(wethReserveData.variableDebtTokenAddress); + const aweth = await getAToken(wethReserveData.aTokenAddress); + + const wethBalance = await weth.balanceOf(signerAddress); + const wethStableDebt = await stableDebtWeth.balanceOf(signerAddress); + const wethVariableDebt = await variableDebtWeth.balanceOf(signerAddress); + const wethTotalDebt = wethStableDebt.add(wethVariableDebt); + const awethBalance = await aweth.balanceOf(signerAddress); + + console.log( + `WETH balance: ${formatUnits(wethBalance, 18)}, aWETH balance: ${formatUnits( + awethBalance, + 18 + )}.` + ); + console.log( + `WETH stable debt: ${formatUnits(wethStableDebt, 18)}, WETH variable debt: ${formatUnits( + wethVariableDebt, + 18 + )}` + ); + + // Lending pool + const user = await lendingPool.getUserAccountData(signerAddress); + + console.log( + `Total collateral usd: ${formatUnits( + user.totalCollateralETH, + 8 + )}, total debt usd: ${formatUnits(user.totalDebtETH, 8)}` + ); + console.log( + `Loan to value: ${formatUnits(user.ltv, 2)}%, health factor: ${formatUnits( + user.healthFactor, + 18 + )}, current liquidation threshold: ${formatUnits(user.currentLiquidationThreshold, 2)}%` + ); +}); diff --git a/tasks/deployments/deploy-UiPoolDataProvider.ts b/tasks/deployments/deploy-UiPoolDataProvider.ts index 9e360db3..798ad0c8 100644 --- a/tasks/deployments/deploy-UiPoolDataProvider.ts +++ b/tasks/deployments/deploy-UiPoolDataProvider.ts @@ -1,9 +1,15 @@ import { task } from 'hardhat/config'; -import { eContractid, eEthereumNetwork, eNetwork, ePolygonNetwork } from '../../helpers/types'; +import { + eArbitrumNetwork, + eContractid, + eEthereumNetwork, + eNetwork, + ePolygonNetwork, +} from '../../helpers/types'; import { deployUiPoolDataProvider } from '../../helpers/contracts-deployments'; import { exit } from 'process'; -task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider contract`) +task(`deploy-UiPoolDataProvider`, `Deploys the UiPoolDataProvider contract`) .addFlag('verify', 'Verify UiPoolDataProvider contract via Etherscan API.') .setAction(async ({ verify }, localBRE) => { await localBRE.run('set-DRE'); @@ -31,6 +37,10 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider incentivesController: '0xd41aE58e803Edf4304334acCE4DC4Ec34a63C644', aaveOracle: '0xC365C653f7229894F93994CD0b30947Ab69Ff1D5', }, + [eArbitrumNetwork.rinkeby]: { + incentivesController: '0x0000000000000000000000000000000000000000', + aaveOracle: '0xbdf16840DDA7DadB502D5008943202F747a1136F', + }, }; const supportedNetworks = Object.keys(addressesByNetwork); diff --git a/tasks/migrations/arbitrum.dev.ts b/tasks/migrations/arbitrum.dev.ts new file mode 100644 index 00000000..1f774355 --- /dev/null +++ b/tasks/migrations/arbitrum.dev.ts @@ -0,0 +1,35 @@ +import { task } from 'hardhat/config'; +import { ConfigNames, loadPoolConfig } from '../../helpers/configuration'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { printContracts } from '../../helpers/misc-utils'; + +task('arbitrum:dev', 'Deploy development enviroment') + .addFlag('verify', 'Verify contracts at Etherscan') + .addFlag('skipRegistry', 'Skip addresses provider registration at Addresses Provider Registry') + .setAction(async ({ verify, skipRegistry }, DRE) => { + const POOL_NAME = ConfigNames.Arbitrum; + await DRE.run('set-DRE'); + + console.log('Migration started\n'); + + console.log('1. Deploy address provider'); + await DRE.run('full:deploy-address-provider', { pool: POOL_NAME, skipRegistry }); + + console.log('2. Deploy lending pool'); + await DRE.run('full:deploy-lending-pool', { pool: POOL_NAME }); + + console.log('3. Deploy oracles'); + await DRE.run('full:deploy-oracles', { pool: POOL_NAME }); + + console.log('4. Deploy Data Provider'); + await DRE.run('full:data-provider', { pool: POOL_NAME }); + + console.log('5. Deploy WETH Gateway'); + await DRE.run('full-deploy-weth-gateway', { pool: POOL_NAME }); + + console.log('6. Initialize lending pool'); + await DRE.run('full:initialize-lending-pool', { pool: POOL_NAME }); + + console.log('\nFinished migrations'); + printContracts(); + });